Javascript 为什么“原始”对象的计算结果为;“对象”;在调试器中?
我正在阅读Kyle Simpson的《YDKJS:这与对象原型》,并查看他的行为授权示例。下面是代码:Javascript 为什么“原始”对象的计算结果为;“对象”;在调试器中?,javascript,debugging,prototype,google-chrome-devtools,prototypal-inheritance,Javascript,Debugging,Prototype,Google Chrome Devtools,Prototypal Inheritance,我正在阅读Kyle Simpson的《YDKJS:这与对象原型》,并查看他的行为授权示例。下面是代码: Foo = { init: function(who) { this.me = who; }, identify: function() { return "I am " + this.me; } }; Bar = Object.create( Foo ); Bar.speak = function() { alert
Foo = {
init: function(who) {
this.me = who;
},
identify: function() {
return "I am " + this.me;
}
};
Bar = Object.create( Foo );
Bar.speak = function() {
alert( "Hello, " + this.identify() + "." );
};
var b1 = Object.create( Bar );
b1.init( "b1" );
var b2 = Object.create( Bar );
b2.init( "b2" );
b1.speak();
b2.speak();
他使用此图来描述这些对象之间的关系:
现在我的问题是:
在Chrome Developer tools中修补此代码时,我看到\uuuuu proto\uuuuu
对象的计算结果为对象
。为什么呢?\uuu proto\uuu
对象不应该描述图中的实际关系吗,其中b1
和b2
委托给Bar
,后者反过来委托给Foo
?为什么这些关系没有在\uuuu proto\uuu
对象中明确命名?毕竟,这个实现使用了Object.create()
方法,并在proto
参数(第一个参数)中放置了一个参数。控制台是否会将该命名参数作为\uuuu proto\uuu
对象的值返回
这并不是那么简单。
\uuuu proto\uuu
属性是指向.constructor
的原型的动态链接
但是,在这些情况下,.constructor
不会被覆盖(尽管它可以在某些手工制作的库中)
当你在寻找对Foo
的引用时,这是一个非常“经典”的观点,与原型继承关系不大,原型继承是从一个具体实例而不是一个类继承的,在JS的情况下,引用(不是标量)而不是副本
tl;dr的原因很简单:对象。create
的构造函数是对象
,{}
的构造函数是对象
和对象。prototype
的构造函数是对象
长途跋涉 首先要知道的是:
这些查找中的名称与变量无关,但通常与函数有关。
曾几何时,可以找到此信息的字段是隐藏的,现在它被发现是一个函数的
.name
属性(function Foo(){}Foo.name;//Foo
),在许多浏览器中(很像\uu proto\uu
)过去是不可见的
第二位:在控制台引用和类型检查中看到的名称不是基于proto,而是基于名为
.constructor
的属性
// Equivalent assignments
var obj1 = { };
var obj2 = new Object();
var obj3 = Object.create(Object.prototype);
obj1.constructor; // Object
obj2.constructor; // Object
obj3.constructor; // Object
如果我们稍微改变一下动态,并引入更“经典”的实例创建方法,即paseé,但将看到ES6中使用类sugar的死灰复燃
function Foo () {
this.isFoo = true;
}
var foo = new Foo();
foo.isFoo; // true
foo.constructor; // Foo
foo.__proto__ === Foo.prototype; // true
foo.__proto__.constructor; // Object
最后一点告诉你,对于你眼前的问题;Foo.prototype
只不过是一个普通的ol'对象
实例。
在JS时代,每个人都在寻找让JS感觉像Java/C的最佳方式,你会看到如下内容:
function Foo () { }
function Bar() { }
Bar.prototype = new Foo();
var foo = new Foo();
var bar = new Bar();
bar instanceof Bar; // true
bar instanceof Foo; // true
一方面,这种方法很有效,因为我们能够在Bar实例上重用Foo的方法。
大。
直接的缺点是Bar
的所有实例共享同一个Foo
实例,包括其所有特定于实例的属性
虽然这种方法与我建议的重用模式相去甚远,但它确实很好地展示了您的困境
// using the last set of assignments
bar instanceof Foo;
// equivalent to:
bar.constructor === Foo; // false
bar.__proto__.constructor === Foo; // true
// not equivalent to
bar.__proto__ == Foo;
更现代形式的“经典”继承(调用super
构造函数,将其他构造函数的原型复制到新构造函数上,等等)可以更好地让您组合和重用方法
但这是以能够依靠\uuu proto\uuu
链来查找这些借来的方法的来源为代价的
历史上,“不利于重用,利于类型检查”模型允许您进行搜索
val.\uuuuu proto\uuuuu.\uuuuu proto\uuuuu.\uuuuuuu proto\uuuuu.(……)\uuuuuuuu proto\uuuuu.构造函数
直到它与您的实例相匹配,或者直到您点击该行末尾的对象
较新的表单将值直接复制到val.\uu proto\uu
(/val.constructor.prototype
,我们在创建val
时看到的是同一个对象),这意味着你的原型链很快就用完了。这个\uuuuuuuuuuuuuu
显示为对象
-但是Foo
和Bar
也一样。你希望它显示为什么?有很好的理由不显示为Foo
-对象不知道它们的名称。@user2357112为什么不呢希望它包含对它链接到的对象的引用?你是如何在chrome中获得所有这些的?感谢你花时间写下这个清晰而彻底的回复!我觉得我欠你一些东西。哈哈!