美文网首页
__proto__ 与 prototype in JavaScr

__proto__ 与 prototype in JavaScr

作者: KEEEPer | 来源:发表于2017-07-18 10:29 被阅读110次

    参考自StackOverflow

    如果你细心的研究过对象内部有什么东西,你会发现,就算我创建一个非常简单的对象,打开它的内部,也会看到许多有趣的东西,而且但凡是对象都会有一个叫做__proto__的属性,如果是类|构造函数|FunctionObject,还会有一个叫做prototype的 *属性|对象 *,比方说:

    var a = new Object()   
    or
    var a = {} 
    

    现在,在全局(global)对象中,创建了一个空的实例(在C++,python,java这一类面向对象语言中,我们喜欢把new创建出来的对象叫做实例对象),那么a就真的是空的实例对象 吗,其实不然。

    展开a实例对象以后 通过VScode观察
    当我们展开这个实例对象 以后看到了a 实例对象 中存在一个__proto__
    属性|对象,那么它是怎么来的呢?如果弄懂了它,那么你对理解原型链继承的本质又接近了一步。

    那么下面我来公布一下答案。JavaScript是一个基于原型链继承的语言,所以我们知道,在javascript世界中所有对象的 *造物主 *就是Object(注意,这里的Object第一个字母是大写)所有的对象最终都会链接到Object这个东西,所以a实例对象的造物主就是Object,很自然,的a 实例对象__proto__其实就是Object的prototype 对象|属性

    a.__proto__ === Object.prototype                        // ==> true
    

    这就意味着,实例对象的__proto__属性就是从创建它的类(也就是被new的那个类)的prototype 属性|对象!!! 划重点

    让我们来看一个更加复杂一点的例子

    如果还想进一步了解真相请继续阅读

    下面是一个在stackoverflow上的一个问题,了解这个问题会很有帮助。

    Q(question):

    这张图片展现每一个(es6中的class类对象与es5中的function对象)对象都有一个prototype构造器函数(Constructor function) Foo 同样也有它自己的__proto__ 对象|属性|特性 ,而且这个属性 继承|引用|来自 Function.prototype,又通过它(Function.prototype)的__proto__属性再次 引用到
    |继承自
    Object.prototype(看到没有,这就是一条原型链)。

    提问者的所展示的实例代码:

    var b = new Foo(20);
    var c = new Foo(30);
    

    完整的示例代码:

    // 一个构造函数(construct function)
    
    function Foo(y) {
      // 这个函数创建实例对象通过
      // 特定的模式: 被这个够着函数创建
      // 创建的*实例对象*都有一个叫做 "y" 的属性
      this.y = y;
    }
     
    // 同时 "Foo.prototype" 存储了指向新的被创建的的对象的*引用(reference)*的原型,
    // 所以我们可能利用它来定义 *被共享|被继承* 的属性(properties)或者方法(methods),
    // 所以同样的,在之前的例子中我们有:
     
    // 被继承的属性 "x"
    Foo.prototype.x = 10;
     
    // 以及被继承的方法 "calculate"
    Foo.prototype.calculate = function (z) {
      return this.x + this.y + z;
    };
     
    // 现在,通过 "pattern" Foo
    //  创建我们的*实例对象* "b" 和 "c"
    var b = new Foo(20);
    var c = new Foo(30);
     
    // 调用被继承的方法
    b.calculate(30); // 60
    c.calculate(40); // 80
     
    // 让我们观察一下我们期望的 *引用(reference)* 属性
    
     
    console.log(
     
      b.__proto__ === Foo.prototype, // true
      c.__proto__ === Foo.prototype, // true
     
      // 同样的 "Foo.prototype" 自动的创建了
      // 一个特别的属性叫做 "constructor",这个属性是一个指向
      // *构造函数*自身的 *引用*;
      // 实例化 "b" 和 "c" *实例对象*的时候,可能会通过
      //*委托(delegation)*找到它 和 用于检测他们的构造器(constructor)
     
      b.constructor === Foo, //==> true
      c.constructor === Foo, // ==> true
      Foo.prototype.constructor === Foo, // ==>true
     
      b.calculate === b.__proto__.calculate, // ==>true
      b.__proto__.calculate === Foo.prototype.calculate // ==>true
     
    );
    

    这段代码之间的关系被展现为下面这幅图

    继承关系图
    这张图是从这里来的

    因此我要 重点强调 * 一下,Foo.prototype只是Foo对象的一个显式的属性,而这个属性时被实例对象b和实例对象* c 引用|指向 的.

    那么prototype__proto__属性有什么区别呢?

    A(answer):

    __proto__是用于查找原型链中方法等等(比方说一般的属性)的实际对象,当你用new来创建一个对象的时候,类(es6中叫class的语法糖)或函数(es5中的都用function来创建类)的prototype是用来构建实例的__proto__对象的对象。
    :

    ( new Foo ).__proto__ === Foo.prototype
    ( new Foo ).prototype === undefined
    

    相关文章

      网友评论

          本文标题:__proto__ 与 prototype in JavaScr

          本文链接:https://www.haomeiwen.com/subject/otlxkxtx.html