javascript中原型链的结尾是啥——null或Object.prototype?
Posted
技术标签:
【中文标题】javascript中原型链的结尾是啥——null或Object.prototype?【英文标题】:What is the end of prototype chain in JavaScript -- null or Object.prototype?javascript中原型链的结尾是什么——null或Object.prototype? 【发布时间】:2016-08-10 03:05:36 【问题描述】:我一直在阅读 javascript 中的原型链,并得出了两个略有不同的定义。据说 JavaScript 中的每个对象都有一个原型,而该原型又具有另一个原型。顶层原型(Grand)也可能有原型,链可以继续。现在链条将停在最后一个物体上。 JavaScript the Good 部分表示链在Object.prototype
终止,MDN 表示null
是链终止的最终链接。
Javascript:好的部分
每个对象都链接到一个原型对象,它可以从中继承属性。 从对象字面量创建的所有对象都链接到
Object.prototype
,这是 JavaScript 的标准对象。
MDN
每个对象都有一个指向另一个对象的内部链接,称为其原型。该原型对象有自己的原型,依此类推,直到 到达一个对象,其原型为 null。 null,顾名思义,没有原型,是这个原型链中的最后一环。
问题:
javascript 中原型链的结尾是什么——null 或 Object.prototype?还是null
和Object.prototype
是一回事?
不是从对象字面量创建的对象是否没有链接到Object.prototype
?
假设我有一个对象var x = len: 4, breadth: 5
。 JavaScript 会自动创建它的原型x.prototype
。原型链有多长? x.prototype
是否只有一个原型 Object.prototype
制作 3 点链?
JavaScript 如何在内部创建自动原型?
【问题讨论】:
创建没有原型的对象的唯一方法不是使用 Object.create 吗? @evolutionxbox 我不太了解Object.create
。我在 JAvascript 中阅读了它的好部分,但无法理解。作者使用了typeof Object.create !== 'function')
但Object.create
已经是一个函数,所以我不知道他的代码将如何执行。
他在 Object.create 出现在 ES5 之前写了这本书。所以 if 语句只是检查 Object.create 是否已经存在。
嗯,这是有道理的。虽然我仍然不明白他的代码。在解决当前的疑问之后,我会再问一个问题。
看看this。它可能有助于向您解释原型链。
【参考方案1】:
javascript中原型链的结束是什么
空。该语言的唯一权限是ECMA-262。
是不是从对象字面量创建的对象,没有链接到 Object.prototype
它们可能是也可能不是,例如
var x = Object.create(null)
[[Prototype]]
为 null,而:
var y = ;
有一个 [[Prototype]]
的 Object.prototype。
假设我有一个对象 var x = len: 4, width: 5。 javascript 会自动创建它的proptotype x.prototype。
没有。函数对象有默认的 prototype 对象。普通对象有一个默认的[[Prototype]]
(即内部原型属性),即Object.prototype(除非按上述方式构造)。
原型链有多长? x.prototype 会不会只有一个原型 Object.prototype 构成一个 3 点链?
两个值:Object.prototype和null。
javascript如何在内部创建自动原型?
不管它喜欢什么,语言规范没有定义实现,只定义行为。
【讨论】:
在最初设计语言时,Object.prototype
是链的末端还是 null
?我的意思是他们最近是否将链尾形式Object.prototype
更改为null
?
从一开始,请参阅 1997 年 6 月的 ECMA-262 ed 1 §15.2.4。
所以这意味着 _Javascript: The Good Parts _ 是错误的。
但是如果Object.prototype
不是链的末端,那么每个对象如何附加toString
方法呢? toString
继承自哪里?
好的部分是正确的,由对象字面量创建的对象继承自 Object.prototype (Douglas Crockford 以其他方式发布将是非同寻常的)。它并没有说这是链条的末端。因此这样的对象有toString。避免这种情况的唯一方法是按照Object.create(null)
答案中的示例。【参考方案2】:
就像,如果纽约有一个信封,里面写着科罗拉多,科罗拉多州有一个信封,里面写着旧金山,旧金山有一个信封,里面写着“没有”。那么旧金山是链条的末端,还是“无”链条的末端?这可能取决于你如何看待它。但有一件事是肯定的:它指向链的上游,用于继承目的(原型继承),直到它到达null
,这意味着不能再往上走。并确保你知道,要向上和向上,它是__proto__
。不是prototype
。
Object.prototype
、Animal.prototype
与 x.__proto__
不同。前者是具有指向原型对象的prototype
属性的函数对象(对象、动物)。而x.__proto__
是原型链向上的方式。往上爬,就是x.__proto__.__proto__
等等。请参阅JavaScript's Pseudo Classical Inheritance diagram 以了解更多信息。
Object.prototype
指的是原型对象。 Quoted from MDN, null
“表示有意不存在任何对象值。它是 JavaScript 的原始值之一。”所以Object.prototype
和null
不是一回事。
所有 JavaScript 对象都有 obj.__proto__
最终指向 Object.prototype
所指的内容。如果不是obj.__proto__
,那么就是obj.__proto__.__proto__
。如果没有,就向上,向上,它会到达Object.prototype
所指的原型对象。而此时,当你上一层时(通过添加.__proto__
,则得到null
。你可以在谷歌浏览器的开发者工具中尝试:
x = a : 1
> Object a: 1
x.__proto__ === Object.prototype
> true
x.__proto__.__proto__
> null
Object.prototype.__proto__
> null
【讨论】:
你的意思是纯对象没有只有纯函数才有的默认原型? 首先阅读有关图表的整篇文章。当您对Fn.prototype
与obj.__proto__
了解更多时,您可以提出更有意义的问题【参考方案3】:
javascript 中原型链的结尾是什么——
null
或Object.prototype
?还是 null 和 Object.prototype 是一回事?
null
。在普通的 JavaScript 环境中考虑这段代码:
var o = ;
console.log(o.i_am_a_property_that_does_not_exist);
该属性访问器操作 (o.i_am_a_property_that_does_not_exist
) 最终转到规范定义的 OrdinaryGet 抽象操作,其中 O 设置为上面的 o
对象和 P em> 设置为"i_am_a_property_that_does_not_exist"
。该操作是这样开始的:
-
断言:IsPropertyKey(P) 为真。
让 desc 成为? O.[GetOwnProperty].
如果desc是未定义,那么
一个。让 parent 成为 ? O.[GetPrototypeOf].
b.如果 parent 为 null,则返回 undefined。
c。返回 ? 父母.[[Get]](P, 接收者).
...
对于我上面的示例,3.c 中的 [[Get]] 操作。最终递归调用 OrdinaryGet 直到我们用完原型。正如我们所见,当我们到达null
时,链就结束了。
此外,完全有可能拥有一个原型链根本不包含Object.prototype
的对象(我们稍后会看到一些)。所以很明显Object.prototype
不可能是原型链的末端。
不是从对象字面量创建的对象是否没有链接到
Object.prototype
?
绝大多数将直接或间接链接到Object.prototype
。考虑:
function Thing()
var t = new Thing();
t
的原型是Thing.prototype
引用的对象。 Thing.prototype
的原型是 Object.prototype
。所以t
链接到Object.prototype
(间接)。
但对象不完全有可能链接到Object.prototype
。这是一种方法:
var o = Object.create(null);
Object.create
让我们使用我们在第一个参数中指定的原型创建一个对象(上面的null
)。所以上面的o
没有原型,它的[[Prototype]]内部槽(对象记住它们的原型)是null
。
这是另一个:
function Thing()
Thing.prototype = Object.create(null);
var t = new Thing();
在这种情况下,虽然t
有原型,但其原型的原型为空; t
根本没有链接到 Object.prototype
。
假设我有一个对象
var x = len: 4, breadth: 5
。 JavaScript 会自动创建它的原型x.prototype
。
对象的原型不是名为prototype
的属性,所以不,JavaScript 引擎不会创建x.prototype
。对象的原型通过其 [[Prototype]] 内部插槽链接,该插槽不可直接观察,但可以通过 Object.getPrototypeOf
检索。 (如果该对象派生自Object.prototype
,那么仅在浏览器上[理论上],您可以使用来自Object.prototype
的Annex B [browser-only] __proto__
property 来访问它。但并非所有对象都具有该属性,因为......并非所有对象继承自Object.prototype
!)
prototype
属性仅用于函数,以确定将哪个对象用作通过new
使用该函数创建的新对象的[[Prototype]]。非函数对象没有它,如果有的话,它不会比名为foo
或bazinga
的属性更特别。
原型链有多长?
x.prototype
会不会只有一个原型Object.prototype
制作一个 3 点链?
您已经接近了,但同样,prototype
属性不是对象的原型,非函数对象通常没有prototype
属性。对于var x = len: 4, breadth: 5
,继承链为:
x
x
的[[Prototype]](即Object.prototype
)
Object.prototype
的[[Prototype]],即null
这么短; 1、2 或 3 取决于您是否要计算 x
以及是否要计算 null
。
JavaScript 如何在内部创建自动原型?
它没有,除了规范定义的那些(例如,Object.prototype
等)。最接近的是,对于所有 function
函数,JavaScript 引擎自动创建一个对象并将该对象分配给函数的 prototype
属性以防万一该函数用作构造函数(通过new
)。 (它不使用箭头函数或生成器。)
【讨论】:
以上是关于javascript中原型链的结尾是啥——null或Object.prototype?的主要内容,如果未能解决你的问题,请参考以下文章
web前端面试题JavaScript第一弹,个人整理部分面试题汇总