修真院Web工程師零基礎全能課html
本節課內容web
JavsScript對象編程
主講人介紹數組
沁修,葡萄藤技術總監瀏覽器
項目經驗豐富,擅長H5移動項目開發。編程語言
專一技術選型、底層開發、最佳代碼實踐規範總結與推廣。函數
直播錄屏版性能
傳送門:https://v.qq.com/x/page/d0740...學習
課程大綱this
一、對象屬性
1.1 什麼是對象
1.2 對象那個的特徵
1.3 訪問對象的屬性
1.4 枚舉對象的屬性
二、建立對象
2.1 經過鍵值對建立
2.2 使用new關鍵字加構造函數
2.3 ES5的新規範object.create()
三、原型與繼承
3.1 prototype
3.2 prototype的相關屬性
3.3 prototype的子方法
四、事件event
4.1 事件類型
4.2 註冊事件處理程序
4.2.1 設置對象屬性
4.2.2 設置html標籤屬性
4.2.3 addEventListener
4.2.4 attachEvent()
4.3 事件的冒泡與捕獲
4.3.1 冒泡
4.3.2 捕獲
4.3.3 應用
1.對象屬性
1.1 什麼是對象?
對象是事物,在現實世界中,一個球,一張桌子,一輛汽車都是對象。
對象就是具備可描述特徵的事物,咱們能夠用某種特定的方式去影響和操做它。
在JS中或者說在面向對象的編程語言中,對象是一系列屬性和方法的組合。
一個屬性包含屬性名和屬性值,這個值能夠是任意類型的數據,也能夠是個函數,這種狀況下函數也被稱爲方法。
而在JS中,你遇到的全部東西幾乎都是對象,那麼咱們來了解一下對象的細節。
1.2 對象的特徵?
對象有屬性,也就是對象的特徵,能夠經過點符號來訪問一個對象的屬性。
objectName.propertyName;
若是把對象比做現實中的一個球,那這個球就是一個對象,擁有屬性,有顏色有大小。這些能夠這樣表示:
var ball = new Object();
ball.color = 「red";
ball.size = 12;
對象還有方法,方法用於定義對象的行爲方式。
好比這個球可能有滾動的方法能夠計算能滾多遠,有彈跳的方法能夠計算跳多高。
能夠這樣表示:
ball.roll = function() {
return this.size * laps
}
1.3 訪問對象的屬性
前面講過咱們能夠經過點符號來訪問對象的屬性,但若是是這樣的狀況,還能經過點符號訪問對象的屬性嗎:
var ball = new Object();
ball.color = 「red";
ball.size = 12;
var spec = 「color」;
ball.spec ??
這裏假設有一個變量spec,咱們須要經過這個變量spec來訪問對象屬性。
但若是用點符號將會訪問ball的spec屬性而後返回一個undefined,說明這裏直接將spec當作了一個屬性而不是變量。
若是咱們想要得到變量的值,來做爲對象的屬性那應該怎麼作呢?
可使用方括號標記訪問,這個標記法在屬性名稱那裏是動態斷定的,這樣就能夠經過存儲在變量中的字符串來訪問屬性了:
ball[spec]; // red
1.4 枚舉對象的屬性
另外咱們能夠經過for in循環語句來枚舉對象的全部屬性:
var ball = {color: 「red」, size: 12, border: 2};
for (var prop in ball) {
console.log(「ball.」 + prop + 「=「 + obj[prop]);
}
// ball.color = red
// ball.size = 12
// ball.border = 2
// 若是但願繼承的屬性不顯示,那麼能夠用hasOwnProperty函數來過濾一遍
var bar = {a: 1, b: 2, c: 3};
function Foo() {
this.color = 'red';
}
Foo.prototype = bar;
var obj = new Foo();
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
console.log(prop);
}
}
也能夠經過Object.keys(obj)的方法來返回一個屬性名集合的數組:
var obj = {a: 「123」, b: 「das」, c: 「web」};
console.log(Object.keys(obj)); // [「a」,」b」,」c」];
var arr = [「a」, 「b」, 「c」];
console.log(Object.keys(arr)); // [「0」,」1」,」2」];
2.建立對象
在JS中建立對象的方法一般有三種:
2.1 第一種
對象字面量的方式,使用花括號,直接經過鍵值對來建立:
var ball = {};
JS每次遇到這個表達式的時候都會建立一遍對象。
2.2 第二種
使用new關鍵字加構造函數:
var ball = new Object();
好比咱們想爲球建立一個類型,而且將這類對象稱爲Ball,擁有一些屬性,那麼能夠經過兩步來建立對象:
1.建立一個構造函數Car來定義這個對象類型,首字母一般爲大寫,這是種習慣用法。
2.經過new建立對象實例:
function Ball(color, size, border) {
this.color = color;
this.size = size;
this.border = border;
}
var myBall = new Ball(「white」, 9, 1);
經過這樣的方法能夠建立許多實例,每一個實例之間互不影響。
2.3 第三種
ES5的新規範,Object.create(),它容許你爲建立的對象選擇其對象原型,不用定義一個構造函數
var Ball = {
color: 「red」,
size: 12
}
var ball1 = Object.create(Ball);
這每一種建立方式繼承的原型對象都不一樣:
第一種的原型是Object.prototype
第二種的原型是構造函數的prototype屬性
第三種的原型是傳入的第一個參數,若是參數爲空則原型爲Object.prototype。
3.原型與繼承
3.1 prototype
咱們先來看看這段代碼:
var foo = {};
console.log(foo.toString()); //[Object Object]
這段代碼意味着什麼?咱們從一個空的對象中取出了一個屬性?
事實上並非的,咱們將要了解一些JS對象的內部工做細節了:
每一個對象除了擁有本身的屬性外,幾乎都包含了一個原型prototype,繼承的屬性能夠經過構造函數的prototype對象找到。
當咱們訪問一個對象所不包含的屬性時,它會從對象的原型中去搜索,原型的原型中去搜索,一直循着原型鏈往上直到搜索到或者到頂部爲止。
說到prototype,其實每一個構造函數都有prototype這個屬性,它指向另外個對象,而這個對象上全部的屬性和方法都會被構造函數的實例所繼承。
這就意味着咱們能夠把不變的屬性和方法,定義到prototype上去:
function Car(color) {
this.color = color;
}
var c1 = new Car(‘white’);
var c2 = new Car(‘red’);
Car.prototype.callColor = function() {
alert(this.color);
}
c1.callColor();
c2.callColor();
這裏所生成的實例c1和c2,他們的callColor方法其實都是同一個內存地址,都是指向的同一個prototype對象,這樣提升了運行效率:
c1.callColor == c2.callColor; // true
3.2 prototype的相關屬性
一般來說,prototype用於設置和返回構造函數的原型對象,方便實例去繼承。
那和它相關的屬性還有些什麼呢?
還有2個,它們幾個糾結於構造函數和實例和原型之間,你們儘可能弄清楚。
__proto__: 設置或返回實例的原型對象
// 1.對象直接量
var p = {}; // 等於new Object()
console.log(p.__proto__ == Object.prototype); // => true
// 2.自定義對象多層繼承
function People(name) {
this.name = name;
}
function Student(age) {
this.age = age;
}
Student.prototype = new People(); // 設置Student的原型爲People對象
var s = new Student(22);
console.log(s.__proto__); // => People 對象
console.log(Student.prototype); // => People 對象
console.log(s.__proto__ == Student.prototype); // => true
constructor: 表示實例對象的構造函數
// 1.內置對象
var str = 'abc';
console.log(str.constructor); // => function String 構造函數
var o = {};
console.log(o.constructor); // => function Object 構造函數
// 2.自定義對象多層繼承 :constructor返回最早調用的構造函數
function People(name) {
this.name = name; // s對象初始化時,先調用People構造函數,再調用Student構造函數
console.log('People調用');
}
function Student(age) {
this.age = age;
console.log('Student調用');
}
Student.prototype = new People(); // 設置Student的原型爲People對象
var s = new Student(22);
console.log(s.constructor); // => function People 構造函數
他們的關係能夠總結爲:
var o = {};
console.log(o.__proto__ === Object.prototype); // true :實例化對象的__proto__等於類的prototype
console.log(o.constructor === Object); // true :實例化對象的constructor等於類
console.log(o.constructor.prototype === Object.prototype); // true :o.constructor.prototype 可表示類的原型。
3.3 prototype的子方法
另外值得說一下的是prototype屬性,它還有兩個輔助方法,幫助咱們去使用它:
isPrototypeOf():
這個方法用來判斷構造函數的原型是不是某個實例的原型:
Ball.prototype.isPrototypeOf(b1);
Ball.prototype.isPrototypeOf(b2);
hasOwnProperty():
這個方法用來判斷實例的一個屬性是否是本地屬性,仍是說是繼承自prototype的屬性:
b1.hasOwnProperty(「color」);
b1.hasOwnProperty(「jump」);
4.事件event
4.1 事件類型
事件類型就是一個用來講明發生什麼類型事件的字符串
例如mouseover表示用戶移動鼠標,keydown表示鍵盤上某個按鍵被按下,onload表示文檔加載完畢。
在web應用中,處理表單、窗口、鼠標和鍵盤是最最經常使用的類型了。
表單類型,好比當用戶提交表單和重置表單時,form元素就會分別觸發submit和reset事件;
當用戶改變單選框複選框這些元素的狀態時,一般會觸發change事件。
窗口類型,則是事件和文檔內容無關,會與瀏覽器窗口自己相關。
好比load事件就是最重要的一個,當文檔和外部資源徹底加載並顯示出來後就會觸發它;
還有當用戶調整窗口大小或滾動的時候會觸發resize事件和scroll事件。
鼠標類型,就是用戶在文檔上移動或點擊時會觸發鼠標事件。
用戶移動鼠標時,就會觸發mousemove事件,不過這個事件發生很是頻繁,千萬不要用來計算密集型的任務;
用戶按下或釋放鼠標按鍵的時候,會觸發mousedown和mouseup事件。
鍵盤類型,當鍵盤聚焦到瀏覽器時,用戶每次按下或釋放按鍵時都會產生事件,傳遞給處理程序的時間對象有keyCode字段,指定了按下或釋放的是哪一個鍵。
4.2 註冊事件處理程序
在指明瞭事件類型後,當特定目標上發生這個類型的事件時,就會調用對應的處理程序,也就是咱們常常所說的觸發了事件。
這就須要咱們註冊事件的處理程序,一般有這樣幾種方式:
4.2.1 設置對象屬性
這種寫法都是由on後面跟着事件名組成:
onclick、onchange、onload等等,而且是全小寫:
// 設置window對象的onload屬性爲一個函數
window.onload = function() {
}
這種方法適合於全部瀏覽器,但缺點是,一個事件目標的一個事件類型下最多就只能有一個處理程序。
更好的辦法後面會講到。
4.2.2 設置html標籤屬性
這種寫法是寫在html標籤的屬性裏,屬性值是一個代碼字符串:
<button onclick=「alert(‘a string!’);」>click here</button>
瀏覽器會把代碼字符串轉換爲代碼來執行。
但這樣作混合js和html,不符合html內容和js行爲分離的標準,所以也不是一個好的寫法。
4.2.3 addEventListener()
在除了IE9以前的全部瀏覽器都支持一個方法,addEventListener(),使用這個方法能夠爲事件目標註冊事件處理程序,它能夠接收3個參數。
第一個是事件類型,這是個字符串但不包括前綴on;
第二個參數是指定事件發生時應該調用的函數;
最後一個參數是布爾值,一般狀況下會傳遞一個false,但若是傳成了true那麼函數會註冊爲捕獲事件處理程序。
<button id=「btn」>click me</button>
<script>
var btn = document.getElementById(「btn」);
btn.addEventListener(「click」, function() {
alert(「clicked!」);
}, false);
</script>
4.2.4 attachEvent()
由於IE9之前的IE不支持addEventListener,因此有個相似的方法attachEvent(),其原理和addEventListener差很少,但也有點不一樣:
1.由於它不支持事件捕獲,所以只有兩個參數:事件類型和處理函數。
2.事件類型傳遞的字符串須要有前綴on
結合這兩種方法,常常看到的事件處理程序註冊的代碼是這樣的:
var btn = document.getElementById(「btn」);
var handler = function() {alert(「hello world」);};
if (btn.addEventListener) {
btn.addEventListener(「click」, handler, false);
} else if (btn.attachEvent) {
btn.attachEvent(「onclick」, handler);
}
這樣就是在支持addEventListener的瀏覽器中就調用它,不然就用attachEvent。
4.3 事件的冒泡與捕獲
有這麼一個思想,咱們都知道一個html頁面就是一顆DOM樹,那麼樹上任意一個節點發生的事件是否均可以經過攀爬這課樹得知呢?
答案是能夠的,這就是事件流。
事件流有冒泡和捕獲兩種。
4.3.1 冒泡
首先來看一下冒泡:
當click事件在div上發生後,click事件沿着DOM樹向上傳播,直到document對象上。
這是一種自下而上的順序,全部的現代瀏覽器都支持事件冒泡。
4.3.2 捕獲
還有一種思路則是捕獲,自上而下,其用意在於事件到達目標以前就捕獲它:
在捕獲過程當中,document對象首先接收到click事件,而後沿着DOM樹一路向下,一直傳播到事件的實際目標div元素。
但由於老版本瀏覽器不支持,所以不多有人使用事件捕獲,因此建議你們放心使用事件冒泡,特殊須要時再考慮事件捕獲。
4.3.3 應用
在瞭解了基本概念以後,就能夠開始考慮實際編碼了:
<body>
<div id=「content">
content
<p id=「child">child</p>
</div>
<script>
var content = document.getElementById(「content」);
var child = document.getElementById(「child」);
content.addEventListener(「click」, function() {
alert(「content」);
}, false);
child.addEventListener(「click」, function() {
alert(「child」);
}, false);
</script>
</body>
能夠看到這是文檔結構很是簡單:
body>#content>#child。
分別在content和child上面綁定了一個點擊事件,因爲addEventListener第三個參數是false,因此是冒泡階段處理綁定事件。
這個時候點擊文本頁面有兩種行爲出現:
1.點擊content文本,彈出content。
這個時候就只處罰了content上的點擊事件,從content文本節點查找,當前節點沒有點擊事件;
而後往上找,找到父級#content有綁定事件執行;
再往上找直到document都沒有綁定的點擊事件,至此冒泡過程結束。
2.點擊child文本,先彈出child,再彈出content
理解了上面的代碼以後,咱們就能夠有事件代理,假設咱們有成千上萬個.child標籤須要綁定點擊事件彈出內容,就無法去挨個綁定了,並且性能也會下降。
這個時候就能夠這樣作:
var content = document.getElementById("content");
content.addEventListener("click", function(e) {
// 把事件對象當作參數傳遞過來,但在IE瀏覽器中,這個e變量是空的,它會在全局的window上,所以這樣寫了以後就能夠兩種方式都支持,保證了瀏覽器的兼容性
var e = e || window.event;
if (e.target.className == "child") {
alert(e.target.innerHTML);
}
}, false);
因爲事件冒泡機制的存在,點擊了.child以後會冒泡到content上,這個時候就會觸發綁定在content上的點擊事件,再利用target找到事件實際發生的元素,就能夠達到預期效果了
以上就是上節課的內容解析啦
想進一步深刻的同窗歡迎加入咱們的IT交流羣828691304共同交流學習!
下節預告
jQuery入門與應用