首先,这个问题与本网站上的其他几个问题非常相似。我已经阅读了它们,但仍有疑问
这两个有所帮助,但并没有让我一路走来:
我有一个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);
我在控制台中看到以下内容:
我不明白的是:
如果我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{}
答案 0 :(得分:1)
让我们一步一步地浏览你的代码,看看我们最终得到了什么。
在下图中,这是命名法:
.prototype
.constructor
.__proto__
或[[Prototype]]
TMath
创建函数时,JS引擎还会创建一个匿名对象,并使用.prototype
和.constructor
属性绑定这两个属性,如下所示:
function foo(){}
/* performed by JS engine */
// foo.prototype = {};
// foo.prototype.constructor = foo;
var TMath = function() {
return new TMath.init();
}
prototype
替换为另一个对象我们正在重新分配链接TMath.prototype
,以便它现在指向新对象。
这个新对象中还有一个匿名函数,由.add()
引用。
并且所述函数带有其自己的默认.prototype
对象。
TMath.prototype = {
add: function(a, b) {
return a+b;
}
};
这个很简单。 只需添加一个新链接到添加新属性的对象/函数。
在我们的例子中,链接是.init()
,属性是匿名函数。
TMath.init = function(){};
prototype
替换为另一个对象就像第2步一样,我们会重新分配链接TMath.prototype
。
但是,我们不是创建新对象,而是将其指向现有对象。
TMath.init.prototype = TMath.prototype;
还在我身边吗?
好!这就是 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
。
您可以通过执行以下操作来确认所有这些:
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/