彻底搞懂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

猜你喜欢

转载自www.cnblogs.com/lyraLee/p/11617712.html