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