Javascript `ECMAScript规范中的新对象`vs`Object`

Javascript `ECMAScript规范中的新对象`vs`Object`,javascript,language-lawyer,ecmascript-5,Javascript,Language Lawyer,Ecmascript 5,因此,我正在研究ES5规范中的新对象和对象的定义。令我惊讶的是: newobject描述了对象构造函数如何工作的整个算法-处理不同类型的值所发生的事情。基本上在非对象上调用ToObject——对象上的标识,并在null和未定义的基础上构建 Object对于null和undefined有一个特殊的第一步,它构建一个对象,然后在原语上调用ToObject,在对象上调用identity 在读了几遍描述之后,它们看起来是一样的。然而,很明显,从规范来看,他们做了一些不同的事情。例如,在数组中,调用新

因此,我正在研究ES5规范中的
新对象
对象
的定义。令我惊讶的是:

  • newobject
    描述了对象构造函数如何工作的整个算法-处理不同类型的值所发生的事情。基本上在非对象上调用
    ToObject
    ——对象上的标识,并在null和未定义的基础上构建
  • Object
    对于null和undefined有一个特殊的第一步,它构建一个对象,然后在原语上调用
    ToObject
    ,在对象上调用identity
在读了几遍描述之后,它们看起来是一样的。然而,很明显,从规范来看,他们做了一些不同的事情。例如,在
数组
中,调用
新数组
被指定为

所以-新对象和对象之间的区别是什么?为什么它们的指定不同?

为方便起见-这里有一个。

对象(窗口)
永远不会克隆
窗口
,但
新对象(窗口)
可能会。所有当前的(可能是所有已知的)实现只返回相同的引用,尽管规范允许实现定义的行为

15.2.1.1的步骤是:

  • 如果值为null、未定义或未提供,则创建并返回一个新的对象,就像使用相同的参数调用标准内置对象构造函数一样
  • 返回到对象(值)
  • ToObject
    (9.9)的定义列出了步骤1(表14)将捕获的几种类型,但对于
    对象
    有一个非常简单的定义:

    结果是输入参数(无转换)

    它明确声明输入参数将按原样返回,因此它们应该是相等的引用(
    ==

    新对象的定义(15.2.2.1)在步骤1中具有类似的类型检查链,但对象的步骤(1.a)是:

    一,。如果该值是本机ECMAScript对象,则不要创建新对象,只需返回值即可

    二,。如果该值是一个主机对象,则将执行操作,并以依赖于实现的方式返回结果,这可能取决于主机对象

    也就是说,对于任何主机对象
    foo
    ,调用
    对象(foo)
    必须
    ==foo
    ,但是
    新对象(foo)
    可能
    ==foo

    主机对象在4.3.8中定义为

    对象,以完成ECMAScript的执行环境

    列出了一些要包括
    窗口
    历史
    等的主机对象。通过
    新对象(foo)
    运行这些对象应该(但不一定)返回不同的对象

    在任何情况下,除了传递宿主对象之外,
    newobject(foo)
    似乎是一个更复杂的链,它以与
    object(foo)
    几乎相同的方式遵从
    ToObject

    不幸的是,15.2.2.1.1.a.ii声明“结果以依赖于实现的方式返回”,并且没有关于“所采取的行动”的细节,而且Chrome似乎将为所有列出的“主机对象”返回相同的对象(相等的引用)

    使用此脚本检查:

    var对象=[
    /*本机对象*/
    'Object'、'Date'、'Math'、'parseInt'、'eval',
    /*宿主对象*/
    “窗口”、“文档”、“位置”、“历史记录”、“XMLHttpRequest”、“设置超时”
    ];
    函数getDefinedReference(名称){
    如果(eval('typeof'+name)!='undefined'){
    返回eval(名称);
    }否则{
    抛出新错误(“”+name+’未定义。“);
    }
    }
    函数checkIdentity(名称){
    试一试{
    var ref=getDefinedReference(名称);
    var no=新对象(参考);
    var o=对象(参考);
    log(name,ref==no,ref==o,no==o);
    如果(ref==o&&no!==o){
    //确保ref==对象(ref),但不是新对象(ref)
    log(名称为“返回不同的引用”);
    }
    }捕获(e){
    控制台。警告(e);
    }
    }
    对象。forEach(checkIdentity);
    如果(窗口类型!==“未定义”){
    用于(窗口中的var f){
    支票身份(f);
    }
    
    }
    JS room的人(即Jan Drovak)猜测这与主机对象有关,但我无法找出一个真正的区别。
    new Object
    是在主机对象上定义的实现。我仍然希望看到一个例子,说明它何时不是一个标识。这将是一个著名的问题吗?
    当对象作为新表达式的一部分被调用时,它是一个可以创建对象的构造函数。
    这涉及到
    如果值是一个宿主对象,然后执行操作并以依赖于实现的方式返回结果,该方式可能取决于主机对象。
    这取决于实现
    ToObject
    -
    对象:结果是输入参数(无转换)。
    这似乎是主要区别。为什么?可能要允许依赖于
    实现的部分
    为什么不继续询问?您能否找到一个实现和一个主机对象,它们在
    对象
    新对象
    之间有所不同?@BenjaminGruenbaum仍在寻找。我强烈怀疑这是规范允许的,但没有人在使用,但测试套件不会有什么坏处。@AwalGarg两个新创建的对象引用不相等-与
    {}=={}
    @AwalGarg相同整个问题依赖于第二部分,其中它不是null/未定义:-)