Javascript 为什么“原始”对象的计算结果为;“对象”;在调试器中?

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

我正在阅读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( "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中获得所有这些的?感谢你花时间写下这个清晰而彻底的回复!我觉得我欠你一些东西。哈哈!