【知識梳理】3.6原型鏈

1.建立對象

//第一種方式:字面量
    var o1 = {name:"o1"};//{name: "o1"}
    var o2 = new Object({name:"o2"});//{name: "o2"}

    //第二種方式:構造函數
    var M = function(name){this.name = name;};
    var o3 = new M("o3");//M {name: "o3"}

    //第三種方式:Object.create(o4.__proto__===p//true)
    var p = {name:"p"};
    var o4 = Object.create(p);//{}

2.原型、構造函數、實例、原型鏈

原型鏈

原理:ECMAScript中描述了原型鏈的概念,並將原型鏈做爲實現繼承的主要方法。其基本思想是利用原型讓一個引用類型繼承另外一個引用類型的屬性和方法。在JavaScript中,用__proto__ 屬性來表示一個對象的原型鏈。html

任何一個函數,被new使用了,new後面的函數就是一個構造函數。構造函數能夠經過new運算符來生成一個實例數組

在聲明一個(構造)函數的時候,js引擎會自動給它加上一個prototype屬性,此屬性會初始化一個空對象,即向原型對象M.prototype.constructor===M;返回true瀏覽器

原型對象怎麼能區分是被哪個構造函數引用的呢?原型對象中有一個構造器(constructor),默認的是聲明的構造函數。o3.__proto__===M.prototype;返回true函數

小提示:

1.實例對象只有__proto__,沒有prototype屬性。
2.構造函數有prototype屬性。(也有__proto__,由於函數也是一個對象。M.__proto__===Function.prototype;返回true。)測試

3.instanceof的原理

instanceof

instanceof的原理:用來判斷實例對象的__proto__屬性和構造函數的prototype屬性是否是同一個引用。/ 判斷類(構造函數)的prototype對象是否存在於實例對象的原型鏈上。是則返回true。this

  • o3 instanceof M;返回true(o3.__proto__===M.prototype;返回true)
  • o3 instanceof Object;返回true(M.prototype.__proto__===Object.prototype;返回true)
  • M instanceof Function;返回true。
  • M instanceof Object;返回true。

*使用 instanceof 判斷 引用類型 屬於哪一個 構造函數 的方法。spa

*判斷一個對象是否爲數組:arr instanceof Arrayprototype

*判斷一個對象的構造函數用constructor比較合理code

  1. o3.__proto__.constructor===M;//true
  2. o3.__proto__.constructor===Object;//false

4.new運算符

  1. 先建立一個新對象,繼承構造函數的原型對象;(繼承自foo.prototype
  2. 當構造函數foo被執行時,傳入相應的參數,同時this指向這個新實例;
  3. 若是構造函數沒有返回對象,那麼new出來的結果爲第一步建立的對象;若是構造函數返回了一個「對象」,那麼這個對象會取代整個new出來的結果。
  • 建立一個新對象;
  • this指向這個新對象;
  • 執行代碼,即對this賦值
  • 返回this
//模擬new運算符

var new2 = function(func){
    var o =Object.create(func.prototype); //第一步
    var k =func.call(o);//第二步
    //第三步
    if(typeof k ==="object"){
        return k;
    }else{
        return o;
    }
}

//驗證
o6=new2(M)//建立一個新對象
o6 instanceof M//rue
o6 instanceof Object//true
o6.__proto__.constructor===M//true

5.原型規則和示例

  1. 全部的引用類型(對象、數組、函數),都具備對象特性,便可自由擴展屬性(除了null);
  2. 全部的引用類型(對象、數組、函數),都有一個__proto__屬性,屬性值是一個普通的對象;
  3. 全部的函數,都有一個prototype屬性,屬性值也是一個普通的對象;
  4. 全部的引用類型(對象、數組、函數),__proto__屬性值指向他的構造函數的prototype屬性值;obj.__proto__ === Object.prototype
  5. 當試圖獲得一個對象的某個屬性時,若是這個對象自己沒有這個屬性,那麼會去他的__proto__(即他的構造函數的prototype)中尋找。
//構造函數
function Foo(name,age){
    this.name = name;
}
Foo.prototype.alertName = function(){
    alert(this.name);//this是f
}
//建立實例
var f = new Foo('zhangsan');
f.printName = function(){
    console.log(this.name);//this是f
}
//測試
f.printName();
f.alertName();

圖片描述

6.循環對象自身的屬性

var item;
for(item in f){
    // 高級瀏覽器已經在 for in 中屏蔽了來自原型的屬性
    // 可是這裏建議仍是加上這個判斷,保證程序的健壯性
    if(f.hasOwnProperty(item)){
        console.log(item);
    }
}

7.畫一個原型鏈

畫出一下代碼的原型鏈,便於理解。htm

//構造函數
function Foo(name,age){
    this.name = name;
    this.age = age;
    //return this; // 默認有這一行
}
var f = new Foo('zhangsan',21);

原型鏈示例

8.手寫一個原型鏈繼承的例子

function Elem(id){
    this.elem = document.getElementById(id);
}

Elem.prototype.html = function(val){
    var elem = this.elem;
    if(val){
        elem.innerHTML = val;
        return this;//鏈式操做
    }else{
        return elem.innerHTML;
    }
}

Elem.prototype.on = function(type,fn){
    var elem = this.elem;
    elem.addEventListener(type,fn);
    return this;//鏈式操做
}

var div1 = new Elem('test');
div1.html('<p>hello world </P>').on('click',function(){console.log('clicked');})
相關文章
相關標籤/搜索