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?还是nullObject.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.prototypenull

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.prototypeAnimal.prototypex.__proto__ 不同。前者是具有指向原型对象的prototype 属性的函数对象(对象、动物)。而x.__proto__ 是原型链向上的方式。往上爬,就是x.__proto__.__proto__等等。请参阅JavaScript's Pseudo Classical Inheritance diagram 以了解更多信息。

    Object.prototype 指的是原型对象。 Quoted from MDN, null “表示有意不存在任何对象值。它是 JavaScript 的原始值之一。”所以Object.prototypenull 不是一回事。

    所有 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.prototypeobj.__proto__ 了解更多时,您可以提出更有意义的问题【参考方案3】:

javascript 中原型链的结尾是什么——nullObject.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.如果 parentnull,则返回 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]]。非函数对象没有它,如果有的话,它不会比名为foobazinga 的属性更特别。

原型链有多长? x.prototype 会不会只有一个原型 Object.prototype 制作一个 3 点链?

您已经接近了,但同样,prototype 属性不是对象的原型,非函数对象通常没有prototype 属性。对于var x = len: 4, breadth: 5,继承链为:

x x的[[Prototype]](即Object.prototypeObject.prototype的[[Prototype]],即null

这么短; 1、2 或 3 取决于您是否要计算 x 以及是否要计算 null

JavaScript 如何在内部创建自动原型?

它没有,除了规范定义的那些(例如,Object.prototype 等)。最接近的是,对于所有 function 函数,JavaScript 引擎自动创建一个对象并将该对象分配给函数的 prototype 属性以防万一该函数用作构造函数(通过new)。 (它不使用箭头函数或生成器。)

【讨论】:

以上是关于javascript中原型链的结尾是啥——null或Object.prototype?的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript中原型链的那些事

web前端面试题JavaScript第一弹,个人整理部分面试题汇总

关于javascript中原型和原型链的理解

JavaScript原型链的理解

秒懂javascript的原型(prototype)对象原型链的前世今生

介绍下Javascript原型和原型链的特点?