徹底搞懂prototype和__proto__


prototype是函數特有的屬性,是Function的靜態屬性;__proto__是對象特有的屬性。

因為函數本身是一種對象,所以函數既有prototype屬性也有__proto__屬性。

當函數使用prototype屬性時,是作為構造函數使用;

當函數使用__proto__屬性時,是作為一個對象使用。

另外,__proto__屬性內部屬性,盡量不要使用。可以用setPrototypeOf()和getPrototypeOf()代替。

1)普通函數分別取值

    function C() {}
    console.log(C.prototype);
    /*{ constructor: function C(){},__proto__: Object }*/
    // 使用__proto__時,是普通函數對象,原型對象指向Funtion的prototype屬性
    console.log(C.__proto__ === Function.prototype);

對於普通函數來說,prototype屬性和__proto__屬性都是可讀寫屬性。

給prototype賦值,會改變函數的原型對象和上面的構造函數。

    function C() {}
    function D() {}
    C.prototype = new D();
    console.log(Object.getOwnPropertyDescriptor(C, 'prototype'));
    /* {value: D, writable: true, enumerable: false, configurable: false} //可寫 */
    console.log(C.prototype.constructor === D); // true

2)class類分別取值,和普通函數一樣

  class A{}
  console.log(A.prototype);
  // {constructor: ƒ, __proto__: Object}
  console.log(A.__proto__ === Function.prototype);// true

但是,在class中,prototype屬性是只讀的

  class A{}
  class B{
    add(){console.log('add')}
    static add(){console.log('static add')}
  }
  const a = new A();
  const b= new B();
  console.log(Object.getOwnPropertyDescriptor(A, 'prototype'));
  // {value: {…}, writable: false, enumerable: false, configurable: false}; // 只讀
  A.__proto__ = B; // 靜態屬性方法繼承
  b.add(); // add
  // a.add(); ❌ 不存在
  A.add(); // static add
  A.prototype.__proto__ = B.prototype; // 實例屬性方法繼承
  a.add(); // add

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM