Javascript 对象(一) 对象原型

  1. 每个对象拥有一个原型对象

    如何访问对象的原型对象:

    function Foo() {}
    
    let foo = new Foo();
    const log = console.log;
    
    log(foo.__proto__);
    log(Object.getPrototypeOf(foo));
    log(Foo.prototype);
    
    log(Foo.prototype === foo.__proto__); // true
    log(Foo.prototype === Object.getPrototypeOf(foo)); // true
    log(foo.__proto__ === Object.getPrototypeOf(foo)); // true
    

  2. 普通函数的 prototype 上有两个属性:constructor 和 __proto__,前者指向构造函数自身,后者指向这个原型对象(Foo.prototype)的原型对象(也就是 Object.prototype)。

  3. Object 的 prototype 中没有 __proto__,直接打印 Object.prototype.__proto__ 输出 null

  4. doSomething.prototype.foo = "bar"; vs doSomething.foo = "bar";

    这两种写法肯定不一样,前者 instance 可以访问到,后者 instance 无法访问(返回 undefined)。在原型链上的区别是:前者将 foo 作为 prototype 的一个属性,而后者将 foo 作为 constructor 的一个属性。

  5. 实例的 constructor 属性

    每个实例对象都从原型中继承了一个constructor属性,该属性指向了用于构造此实例对象的构造函数。

  6. 原型的 constructor 属性

    从 2 可以看到,每个构造函数的原型上有一个 constructor 属性,这个属性也有 prototype 和 __proto__ 属性。

    另一方面,Person()函数是Person.prototype的构造函数
    来自 <https://developer.mozilla.org/zh-CN/docs/Learn/JavaScript/Objects/Inheritance>

    其中,prototype 属性指向 Bar.prototype,也就是一个递归的过程。

    而 __proto__ 属性指向 Function.prototype。

    因此,下面的表达式输出 true:

  7. 通过 6 可以知道,Bar.prototype 的 constructor 就是指这个原型对象的构造函数,也就是 Bar() 函数。

    所以,Bar.prototype.constructor.prototype 也就是 Bar()(Bar.prototype.constructor) 的原型了。

    再所以,Bar.prototype.constructor.__proto__ 也就是 Bar()(Bar.prototype.constructor)这个函数本身(就是一个函数,和它的原型没有关系)的 __proto__(原型)自然是指向 Function.prototype,也就是 8 所解释的内容。

    而 Bar.prototype 的 __proto__ 属性指向这个原型对象的原型对象,也就是 Object.prototype,这里的 __proto__ 其实已经和 Bar 没有关系了。

  8. 所有的函数都是 Function 构造函数的一个实例,所以函数也有 __proto__ 属性

  9. 不同变量的位置

    位置 结果
    定义在构造函数内 出现在实例上
    定义在构造函数名上 出现在原型的 constructor 属性上
    定义在原型对象上 出现在原型上
    function Foo() {
      this.width = 200;
      this.height = 300;
    }
    Foo.bar = 'haha';
    Foo.prototype.width = 400;
    Foo.prototype.weight = 500;
    
    let foo = new Foo();
    const log = console.log;
    
    log(foo);
    log(foo.bar); // undefined
    log(foo.width); // 200
    log(foo.height); // 300
    log(foo.weight); // 500
    

参考:

posted @ 2020-07-05 11:10  Ainsliaea  阅读(250)  评论(0编辑  收藏  举报