ECMAScript规范中的`new Object` vs`Object` [英] `new Object` vs `Object` in the ECMAScript spec
问题描述
所以,我在定义什么是 new Object
和 Object
do时,看看ES5规范。令我惊讶的是:
-
new Object
描述了对象构造函数的整个算法工作 - 处理不同类型的值所发生的事情。基本上在非对象上调用ToObject
- 对象上的标识和构建为null和undefined。 -
Object
在null和undefined中有一个特殊的第一步,它构建一个对象,然后在对象的原语和标识上调用ToObject
。
几次阅读说明后 - 他们似乎相同。但是,从规范中可以清楚地看出它们某些是不同的。例如,在 Array
中 - 调用 new array
被指定为函数调用数组(...)
等效于对象创建表达式 new Array(...)
使用相同的参数。
所以 - 新对象$ c之间有什么区别$ c>和
对象
?他们为什么以不同的方式指定?
为了方便 - 这里是一个链接到规范。
对象(窗口)
永远不会克隆窗口
,但新对象(窗口)
可能。所有当前 - 可能都是已知的 - 实现只返回相同的引用,尽管规范允许实现定义的行为。
15.2.1.1的步骤说:
- 如果value为null,未定义或未提供,则创建并返回一个新的Object对象,就像标准一样已使用相同参数调用内置Object构造函数
- 返回ToObject(值)。
ToObject
(9.9)的定义列出了步骤1(表14)中将捕获的几种类型,但是对于 Object
有一个非常简单的定义:
结果是输入参数(没有转换) )。
它明确指出输入参数将按原样返回,因此它们应该是相等的引用( ===
)。
new Object
的定义(15.2。 2 .1)在步骤1中有类似的类型检查链,但对象(1.a)的步骤是:
i 。如果值是本机ECMAScript对象,则不要创建新对象,只需返回值。
ii。如果值是宿主对象,则执行操作并以依赖于实现的方式返回结果,该方式可能取决于宿主对象。
也就是说,对于任何主机对象 foo
,调用 Object(foo)
必须 === foo
但新对象(foo)
可能 === foo
。
主机对象在4.3.8中定义为
提供的对象由主机环境完成ECMAScript的执行环境。
此答案列出了一些主机对象,包括窗口
,历史记录
等。通过 new Object(foo)
运行它们(但不必)返回另一个对象。
在任何情况下但传递一个主机对象, new Object(foo)
似乎是一个更复杂的链条推迟至 ToObject
与 Object(foo)
的方式大致相同。
不幸的是,15.2.2.1.1.a.ii声明结果以依赖于实现的方式返回并且没有关于采取的行动的具体细节,Chrome似乎将返回所有列出的主机对象的相同对象(相同的引用)。
使用此脚本检查:
var objects = [/ * Native objects * /'Object','Date','Math','parseInt',' eval',/ * Host objects * /'window','document','location','history','XMLHttpRequest','setTimeout']; function getDefinedReference(name){if(eval('typeof'+ name) !=='undefined'){return eval(name); } else {throw new Error(''+ name +'未定义。'); function checkIdentity(name){try {var ref = getDefinedReference(name); var no = new Object(ref); var o = Object(ref); console.log(name,ref === no,ref === o,no === o); if(ref === o&& no!== o){//确保ref === Object(ref)但不是新的Object(ref)console.log(name,'返回不同的引用。') ; } catch(e){console.warn(e); objects.forEach(checkIdentity); if(typeof window!=='undefined'){for(窗口中的var f){checkIdentity(f); }
找不到任何<$ c $的对象c>对象和新对象
的行为方式不同。 @ Xotic750似乎是正确的,它可以依赖于实现,但没有人使用它。
So, I'm looking at the ES5 specification at the definition of what new Object
and Object
do. To my surprise:
new Object
describes a whole algorithm of how the object constructor works - treating what happens with different kinds of values. Basically callsToObject
on non objects - identity on objects and builds on null and undefined.Object
has a special first step for null and undefined where it builds an object and then callsToObject
on primitives and identity on objects.
After reading the description a few times - they seem identical. However, clearly from the spec they do something different. For example in Array
- calling new Array
is specified as the function call Array(…)
is equivalent to the object creation expression new Array(…)
with the same arguments.`
So - what is the difference between new Object
and Object
? Why were they specified differently?
For ease - here's a link to the spec.
Object(window)
will never clone window
but new Object(window)
might. All current -- potentially all known -- implementations just return the same reference, although the spec allows for implementation-defined behavior.
The steps for 15.2.1.1 say:
- If value is null, undefined or not supplied, create and return a new Object object exactly as if the standard built-in Object constructor had been called with the same arguments
- Return ToObject(value).
The definition of ToObject
(9.9) lists a few types that will be caught by step 1 (in table 14), but for Object
has a very simple definition:
The result is the input argument (no conversion).
It explicitly states that the input argument will be returned as-is, so they should be equal references (===
).
The definition for new Object
(15.2.2.1) has a similar chain of type-checks in step 1, but the step for objects (1.a) is:
i. If the value is a native ECMAScript object, do not create a new object but simply return value.
ii. If the value is a host object, then actions are taken and a result is returned in an implementation-dependent manner that may depend on the host object.
That is, for any host object foo
, the call Object(foo)
must === foo
but new Object(foo)
may === foo
.
Host objects are defined in 4.3.8 to be
object supplied by the host environment to complete the execution environment of ECMAScript.
This answer lists a few host objects to include window
, history
, etc. Running those through new Object(foo)
should (but doesn't have to) return a different object.
In any case but passing a host object, new Object(foo)
seems to be a more complicated chain that defers to ToObject
in much the same way as Object(foo)
.
Unfortunately, 15.2.2.1.1.a.ii states that the "result is returned in an implementation-dependent manner" and has no specifics as to the "actions [that] are taken" and it appears that Chrome will return the same object (equal references) for all of the listed "host objects."
Using this script to check:
var objects = [
/* Native objects */
'Object', 'Date', 'Math', 'parseInt', 'eval',
/* Host objects */
'window', 'document', 'location', 'history', 'XMLHttpRequest', 'setTimeout'
];
function getDefinedReference(name) {
if (eval('typeof ' + name) !== 'undefined') {
return eval(name);
} else {
throw new Error('' + name + ' is not defined.');
}
}
function checkIdentity(name) {
try {
var ref = getDefinedReference(name);
var no = new Object(ref);
var o = Object(ref);
console.log(name, ref === no, ref === o, no === o);
if (ref === o && no !== o) {
// Make sure ref === Object(ref) but not new Object(ref)
console.log(name, 'returns different references.');
}
} catch (e) {
console.warn(e);
}
}
objects.forEach(checkIdentity);
if (typeof window !== 'undefined') {
for (var f in window) {
checkIdentity(f);
}
}
doesn't find any objects where Object
and new Object
behave differently. @Xotic750 seems to be right that it can be implementation-dependent, but nobody is using it.
这篇关于ECMAScript规范中的`new Object` vs`Object`的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!