__proto__与javascript中的原型继承

时间:2015-08-19 17:12:12

标签: javascript prototype prototypal-inheritance

首先,这个问题与本网站上的其他几个问题非常相似。我已经阅读了它们,但仍有疑问

这两个有所帮助,但并没有让我一路走来:

我有一个javascript框架/库的基本设置:

(function(global){

    var TMath = function() {
        return new TMath.init();
    }

    TMath.prototype = {
        add: function(a, b) {
            return a+b;
        }
    };

    TMath.init = function(){};

    TMath.init.prototype = TMath.prototype;

    global.TMath = global.$$ = TMath;

})(window);

当我像这样运行时:

var test = $$()

console.log(test);

我在控制台中看到以下内容:

enter image description here

我不明白的是:

如果我console.log test.__proto__,我会Object{}

我不应该TMath.Init.prototype,因为function constructor我的test实例是创建的吗?

这是一个发生这种情况的例子:

function Person(name){
    this.dob = dob
 }; 

var person = new Person("name");

console.log(person.__proto__);

这会输出Person{} Object{}

1 个答案:

答案 0 :(得分:1)

让我们一步一步地浏览你的代码,看看我们最终得到了什么。

在下图中,这是命名法:

  • Elipse = function
  • Rectangle = object
  • 箭头=财产
    • p = .prototype
    • c = .constructor
    • P = .__proto__[[Prototype]]
  • 所有匿名项都是空形状,所有命名项都包含名称

1)创建一个函数TMath

创建函数时,JS引擎还会创建一个匿名对象,并使用.prototype.constructor属性绑定这两个属性,如下所示:

function foo(){}

/* performed by JS engine */
// foo.prototype = {};
// foo.prototype.constructor = foo;


var TMath = function() {
    return new TMath.init();
}

enter image description here

2)将函数prototype替换为另一个对象

我们正在重新分配链接TMath.prototype,以便它现在指向新对象。

这个新对象中还有一个匿名函数,由.add()引用。 并且所述函数带有其自己的默认.prototype对象。

TMath.prototype = {
    add: function(a, b) {
        return a+b;
    }
};

enter image description here

3)向对象或函数

添加属性

这个很简单。 只需添加一个新链接到添加新属性的对象/函数。

在我们的例子中,链接是.init(),属性是匿名函数。

TMath.init = function(){};

enter image description here

4)将函数prototype替换为另一个对象

就像第2步一样,我们会重新分配链接TMath.prototype。 但是,我们不是创建新对象,而是将其指向现有对象。

TMath.init.prototype = TMath.prototype;

enter image description here

让我们稍微清理一下图。

enter image description here

5)实例化

还在我身边吗?

好!这就是 magic 发生的地方。

执行var test = $$()时,您实际上正在执行var test = TMath(),这只是var test = new TMath.init()

我们甚至可以说这是完全相同
var test = new <function referenced by TMath.init>()

在调用函数时使用new时,以下规则适用:

  

如果在分配中使用new,则返回的对象将提供属性.__proto__   
  (或[[Prototype]]),它是对引用的对象的引用   
  构造函数的.prototype

因此,创建的对象(在本例中为test)具有指向__proto__的属性TMath.init.prototype

enter image description here

您可以通过执行以下操作来确认所有这些:

console.log(test.__proto__ === TMath.init.prototype) // true
console.log(test.__proto__ === TMath.prototype) // true

结论

确实你最初的想法是正确的

  

如果我console.log test.\_\_proto\_\_,我会Object{}

     

我不应该得到TMath.Init.prototype,因为那是我的test实例创建的函数构造函数吗?

为了掌握JS的这些核心概念,我高度建议阅读http://www.javascripttutorial.net/javascript-prototype/