原型及原型鏈

什么是原型

js中的原型指的是一個(gè)對象可以從另一個(gè)對象繼承特性。每個(gè)對象都有一個(gè)原型對象,對象以其原型對象為模板,繼承其屬性,方法。原型對象也有自己的原型對象,這樣一層一層,通常稱為原型鏈。

準(zhǔn)確來說,這些屬性和方法,定義在對象的構(gòu)造函數(shù)(constructor functions)之上的prototype屬性上面,而不是對象實(shí)例本身。

js中鏈接對象實(shí)例和原型的是_proto_,它是從構(gòu)造函數(shù)的prototype派生的,之后上溯到原型鏈,在構(gòu)造器中找到這些屬性和方法。

js中不是所有的對象都可以作為原型對象,每個(gè)對象都是繼承自O(shè)bject,但是我們主動(dòng)設(shè)置一個(gè)對象的原型為另一個(gè)對象。

prototype屬性

繼承的屬性和方法被定義在prototype屬性上,prototype屬性的值是一個(gè)對象。

constructor屬性

每個(gè)實(shí)例對象都從原型中繼承了一個(gè)constructor屬性,該屬性指向了用于構(gòu)造此實(shí)例對象的構(gòu)造函數(shù)。


構(gòu)造函數(shù),原型,實(shí)例之間的關(guān)系


下面我們將通過一些例子來看一下

    //構(gòu)造函數(shù)1
    function Person( name,age ){
      this.name = name;
      this.age = age;
    };
    //構(gòu)造函數(shù)2
    function Test (){

    }
    //實(shí)例1
    var person1 = new Person("小明", 21);
    //原型鏈為: person1 ====> Person  ====> Object ====> null

    console.log(person1.constructor);
    /*output:
    person1.constructor指向構(gòu)造函數(shù)Person
    ? Person(name, age) {
      this.name = name;
      this.age = age;
    }
    */
    console.log(person1.__proto__);
    console.log(Person.prototype);
    /*output:
    {
      constructor: ? Person(name, age)
      __proto__: Object
    }
     */
    console.log(person1.__proto__ === Person.prototype); //true
  
    //實(shí)例2;
    var person2 = new Test();
    //把實(shí)例person1作為person2的原型
    person2.__proto__ = person1;
    //原型鏈為: person2 ====> person1 ===> Person ===> Object ====>null
    console.log(person2.name) //小明,繼承自person1
    console.log(person2.constructor);
    /*output:
    ? Person(name, age) {
      this.name = name;
      this.age = age;
    }
    */
    console.log(person2.__proto__);
    /*output:
    {
    Person 
      age: 21
      name: "小明"
      __proto__:
      {
      constructor: ? Person(name, age)
      __proto__: Object
      }
    }
     */
    console.log(person2.__proto__.__proto__ === Person.prototype); //true

    //實(shí)例3
    //create() 實(shí)際做的是從指定原型對象創(chuàng)建一個(gè)新的對象。這里以 person1 為原型對象創(chuàng)建了 person3 對象。
    var person3 = Object.create(person1);
    //原型鏈為: person3 ====> person1 ===> Person ===> Object ====>null

    console.log(person3.__proto__);
    /*output:
    {
    Person 
      age: 21
      name: "小明"
      __proto__:
      {
      constructor: ? Person(name, age)
      __proto__: Object
      }
    }
     */

不改變對象的原型鏈繼承另一個(gè)對象的方法

    //構(gòu)造函數(shù)1
    function Person( name,age ){
      this.name = name;
      this.age = age;
    };
    //構(gòu)造函數(shù)2
    function Test (){

    }

    //方法一:
    var person4 = new Test();
    //用call或者apply來改變this,在person4的作用域里面去執(zhí)行Person
    //Person.call(person4);
    Person.apply(person4);
    console.log(person4.__proto__);
    /*
    constructor: ? Test()
    __proto__: Object
    */

  //方法二: 可以直接在構(gòu)造函數(shù)里面使用apply或者call
  //比如:
  function Test (){
    Person.call(this);
  }


四個(gè)拓展原型鏈的方法

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Inheritance_and_the_prototype_chain#%E6%80%BB%E7%BB%93%EF%BC%9A4_%E4%B8%AA%E7%94%A8%E4%BA%8E%E6%8B%93%E5%B1%95%E5%8E%9F%E5%9E%8B%E9%93%BE%E7%9A%84%E6%96%B9%E6%B3%95


new操作符做了什么事情

//new 的過程
var obj = new Object(); //創(chuàng)建一個(gè)新對象
obj.__proto__ = A.prototype;  //讓obj的__proto__指向A.prototype
A.call(obj)   //在obj的作用環(huán)境執(zhí)行構(gòu)造函數(shù)的代碼,使this指向obj
return obj    //返回實(shí)例對象
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容