2.原型和原型鏈

---------------------- 題目-------------------------

1. 如何準(zhǔn)確判斷一個變量是數(shù)組類型
   //變量 instanceof Array
   var arr = [];
   arr instanceof Array;//true
     
     typeof arr;  //object,typeof是無法判斷是否是數(shù)組的
2. 寫一個原型鏈繼承的例子
    function Person(name,sex){
        this.name = name;
        this.sex = sex;
    }
    
    Person.prototype.showName=function(){
        alert(this.name);
    };
    
    Person.prototype.showSex = function(){
        alert(this.sex);
    };
    
    function Worker(name,sex,job){
        Person.call(this,name);
        this.job = job;
    }
    
     for(var i in Person.prototype){
        Worker.prototype[i]=Person.prototype[i];
    }
    
    Worker.prototype.showJob=function(){
        alert(this.job);
    };
    var P1= new Person('blue','men');
    var W1= new Worker('leo','men','coder');
    
    P1.showName();
    P1.showSex();
    
    W1.showName();
    W1.showSex();
    W1.showJob();
*貼近實際開發(fā)原型鏈繼承的例子
     /*------------封裝DOM查詢------------------*/
    //(獲取一個dom節(jié)點,獲取內(nèi)容,改變內(nèi)容,綁定事件)
        function Element(id){
            this.elem = document.getElementById(id);
      }
    
    Element.prototype.html=function(val){
        var elem  = this.elem;
        if(val){
           elem.innerHTML = val;
           //把整個對象(div1)返回出去
           return this;//鏈?zhǔn)讲僮?        }else{
            //把當(dāng)前html結(jié)構(gòu)返回出來
            return elem.innerHTML;
        }
        
    };
    
    Element.prototype.on=function(type,fn){
        var elem = this.elem;
        elem.addEventListener(type,fn);
        //把整個對象(div1)返回出去
         return this;//鏈?zhǔn)讲僮?    };
    
    var div1 = new Element('main-outer');
    
    div1.html('<p>test immoc</p>').on('click',function(){
        alert('click');
    }).html('<p>javascript</p>');
3. 描述new一個對象的過程(構(gòu)造函數(shù))
    1. 創(chuàng)建一個新對象
    2.this指向這個新對象
    3. 執(zhí)行代碼,即對this賦值
    4. 返回this
    
     function Foo(name,age){
        this.name = name;
        this.age = age;
        this.class = 'class-1';
        //構(gòu)造函數(shù)默認(rèn)不要寫return this,讓它自己返回就
        // return this //默認(rèn)有一行
    }

    // new 就是構(gòu)造函數(shù)形成一個實例的過程
      var f = new Foo('zhangsan',20);
    //var f1 = new Foo('lisi',22);//創(chuàng)建多個對象
    // 考察構(gòu)造函數(shù) new 原理
4. zepto(或其他框架)源碼中如何使用原型鏈
   * 閱讀源碼是高效提高技能的方式
   * 不能埋頭苦鉆有技巧在其中
   * 慕課網(wǎng)搜“zepto設(shè)計和源碼分析”

--------------------------- 知識點-------------------------------

1. 構(gòu)造函數(shù)
// 大寫字母開頭的函數(shù)是構(gòu)造函數(shù)
// 構(gòu)造函數(shù)類似于模板可以創(chuàng)建多個對象

function Foo(name,age){
    this.name = name;
    this.age = age;
    this.class = 'class-1';
    // return this //默認(rèn)有一行
}

// new 就是構(gòu)造函數(shù)形成一個實例的過程
var f = new Foo('zhangsan',20); 
//var f1 = new Foo('lisi',22);//創(chuàng)建多個對象

//*new一個構(gòu)造函數(shù)返回一個對象的過程 
1、先new的時候把參數(shù)傳進(jìn)去(當(dāng)然也可以不傳)
2、new這個函數(shù)執(zhí)行的時候,函數(shù)里邊的this會先變成一個空對象,
再this.name這些屬性的賦值,賦值完之后默認(rèn)把this return回來,
賦值給f,f就具備了f.name='zhangsan'。
2. 構(gòu)造函數(shù)--擴(kuò)展
// 所有的引用類型(對象、數(shù)組、函數(shù))都有構(gòu)造函數(shù);
//對象有構(gòu)造函數(shù)、數(shù)組有構(gòu)造函數(shù)、函數(shù)也有構(gòu)造函數(shù)
var a ={}其實是var a = new Object()的簡寫;
  a 的構(gòu)造函數(shù)是 Object;
var a = []其實是var a = new Array()的簡寫;
  a 的構(gòu)造函數(shù)是Array 
function Foo(){...}其實是var Foo = new Function(...);
  Foo 的構(gòu)造函數(shù)是Function;
  
  //推薦寫法都推薦前面的寫法:
  var a ={}; var a =[]; function Foo(){...}
* 使用instanceof判斷一個函數(shù)是否是一個變量的構(gòu)造函數(shù);
//判斷一個變量是否為“數(shù)組”:變量 instanceOf Array
3. 原型規(guī)則和示例
* 5條原型規(guī)則
// 原型規(guī)則是學(xué)習(xí)原型鏈的基礎(chǔ)
1.所有的引用類型(數(shù)組、對象、函數(shù)),都具有對象特性,即可自由擴(kuò)展
屬性(除了"null"以外)
var obj = {};  obj.a  =100;
var arr = [];  arr.a =100;
function fn(){}  fn.a =100;
    
2.所有的引用類型(數(shù)組、對象、函數(shù)不包括null),都有一個_proto_(隱式原型)
屬性,屬性值是一個普通的對象
console.log(obj._proto_);
console.log(arr._proto_);
console.log(fn._proto_);

3、所有的函數(shù),都有一個prototype(顯式原型)屬性,屬性值也是一個普通的對象
console.log(fn.prototype);

4、所有的引用類型(數(shù)組、對象、函數(shù)),_proto_屬性值指向(完全等)它的構(gòu)造函數(shù)
的 "prototype"屬性值
// var obj = new Object();
console.log(obj._proto_ === object.prototype);//true

5、當(dāng)試圖得到一個對象的某個屬性時,如果這個對象(引用類型--數(shù)組、函數(shù)、對象)
本身沒有這個屬性,那么會去它的_proto_(即它的構(gòu)造函數(shù)的prototype)中尋找。
//隱式原型等于它的構(gòu)造函數(shù)顯式原型
//*****一個變量本身沒有屬性,它會去它的構(gòu)造函數(shù)的顯式原型中去尋找********/
console.log(obj._proto_ === Object.prototype);
   
//構(gòu)造函數(shù)
function Foo(name,age){
    this.name = name;
}

Foo.prototype.showName=function(){
    alert(this.name);
};

//創(chuàng)建示例
var f = new Foo('zhangsan');

f.consoleName = function(){
    console.log(this.name);
};

//測試
f.consoleName();//'zhangsan'

 //一個變量本身沒有屬性,它會去它的構(gòu)造函數(shù)的顯式原型中去尋找
 //無論是函數(shù)自身的屬性還是原型中得到的一個屬性,函數(shù)執(zhí)行中的this永遠(yuǎn)指向f自身;
f.showName();  //'zhangsan'
*循環(huán)對象的自身屬性*
/**高級瀏覽器已經(jīng)在 for in中屏蔽了來自原型的屬性,但是這里建議大家還是加上這個判斷,保證程序的健壯性 **/
/**在遍歷f的時候判斷一下遍歷出來的item是不是能通過hasOwnProperty驗證;如果通過之后就說明是f自身的屬性,沒通過就說明是f通過原型得到的屬性**/ 

//for in 可以對一個對象進(jìn)行循環(huán)的
var item;
 for(item in f){
    if(f.hasOwnProperty(item)){
     console.log(item);
   }
}

4.原型鏈

原型鏈?zhǔn)疽鈭D.png
原型鏈?zhǔn)纠?png
//構(gòu)造函數(shù)
function Foo(name,age){
    this.name = name;
}
Foo.prototype.showName=function(){
    alert(this.name);
};

//創(chuàng)建示例
var f = new Foo('zhangsan');
f.consoleName=function(){
    console.log(this.name);
};
//測試

f.cosoleName();

/**獲取的f隱式原型(f的構(gòu)造函數(shù)顯式原型里面的定義的一個值就是定義
的showName這個屬性值并且執(zhí)行了)里面的屬性**/
f.showName(); 

/**當(dāng)這個對象沒有這個屬性的時候就會去它自身的一個隱式原型(它構(gòu)造函
數(shù)的顯式原型)中去找***/
//構(gòu)造函數(shù)是Foo  顯式原型是Foo.prototype.中并沒有toString這個東西
/*f.prototype構(gòu)造函數(shù)的顯式原型也是一個對象,在它中尋找t oString這個
方法;要去它的隱式原型(f._proto_._proto_)中去找*/
/**原型鏈(去f的隱式原型(f._proto_)中去找,f._proto_沒有toString
f._proto_也是一個對象),在這個對象里面找toString,還得到它本身的隱式
原型中去找*/
f.toString(); 
5. instanceof--(類型判斷)---是原型鏈一個具體的表現(xiàn)而已)
//用于判斷引用類型屬于哪個構(gòu)造函數(shù)的方法
f instaceof Foo的判斷邏輯是:
//》f的_proto_一層一層往上,能否對應(yīng)到Foo.prototyoe
//》在試著判斷f instanceof Object
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容