javascript autobox?

时间:2013-06-20 14:50:21

标签: javascript

在处理另一个问题时,我创造了这个小提琴:

http://jsfiddle.net/tr2by/

function foo() {
    // console.log(_.isBoolean(this));
    console.log(this === true);
}

foo.call(true); // object:[object Boolean]
foo.apply(true); // object:[object Boolean]

这是自动装箱的一个例子吗?

从值类型转到引用类型。

这是wikipedia def.

3 个答案:

答案 0 :(得分:35)

首先,我假设您正在讨论将原始值自动转换为对象。在JavaScript中有两种情况:

  1. 当您将原始值作为this值传递给.call.apply时(尽管不是严格模式)。
  2. 当您尝试访问原始值的“属性”时,例如"foo bar".split()
  3. 在第一种情况下,转换是永久性的,即this确实将引用一个对象,在第二种情况下,转换仅在内部进行评估期间

    如果您对转换的细节不感兴趣,可以忽略其余的答案。


    <强> 1。原始值为this

    当函数被执行且其this值不是对象时,它将转换为1,至少在非严格模式下。这在ECMAScript 5.1文档中的§10.4.3 Entering Function Code [spec]中有描述:

      

    当控件进入函数对象F中包含的函数代码的执行上下文,提供的调用者thisArg以及调用者提供的argumentsList时,执行以下步骤:

         
        
    1. 如果功能代码是严格代码,请将ThisBinding设置为thisArg
    2.   
    3. 如果thisArgnullundefined,请将ThisBinding设置为全局对象。
    4.   
    5. 如果Type(thisArg)不是Object,请将ThisBinding设置为ToObject(thisArg。)   [...]
    6.   

    正如您在第三步中看到的那样,通过调用ToObject [spec]将值转换为对象。

    <强> 2。财产访问

    当您尝试访问属性(§11.2.1 Property Accessors [spec])时会发生类似情况。这里引用的部分解释了如何评估表达式foo[bar],即如何评估带括号表示法的属性访问。我们感兴趣的部分也适用于点符号。

      

    生产MemberExpression : MemberExpression [ Expression ]的评估如下:

         
        
    1. baseReference成为评估MemberExpression
    2. 的结果   
    3. baseValue成为GetValue(baseReference)   [...]
    4.         

      8.返回Reference值为base且其引用名称为baseValue且其propertyNameString模式标志为{的strict类型的值{1}}。

    重要的一步是最后一步:无论strict评估什么,它都会转换为Reference [spec]类型的值。这是仅在规范中使用的数据类型,并包含有关如何从引用中检索实际值的其他信息(不要与实际JavaScript代码中的对象引用混淆!)。

    要从这样的引用中获取“真实”值/结果,将调用内部函数GetValue(V) (§8.7.1) [spec](就像上面算法中的步骤2一样),其中显示:

      

    MemberExpression是具有原始基值的属性引用时,[[Get]]使用以下GetValue内部方法。使用V作为其base值并使用属性this作为其参数调用它。采取以下步骤:

         
        
    1. P成为O   [...]
    2.   

    示例:

    假设我们有表达式

    ToObject(base)

    这是一个赋值表达式,其计算方法如下:

      

    生产var foo = "BAR".toLowerCase(); 的评估如下:

         
        
    1. AssignmentExpression : LeftHandSideExpression = AssignmentExpression成为评估lref
    2. 的结果   
    3. LeftHandSideExpression成为评估rref
    4. 的结果   
    5. AssignmentExpression成为rval   [...]
    6.   

    步骤1:评估左侧,即标识符GetValue(rref)。如何准确识别标识符并不重要。
    步骤2:评估右侧,即foo。该评估的内部结果将是一个参考值,类似于:

    "BAR".toLowerCase()

    并存储在REFERENCE = { base: "BAR", propertyNameString: "toLowerCase", strict: false }

    第3步:调用rref。引用的GetValue(rref)是值base。由于这是一个原始值,因此将调用"BAR"将其转换为临时 ToObject对象。此外,引用实际上是属性访问,因此String最终将调用GetValue对象上的方法toLowerCase并返回方法的结果。

答案 1 :(得分:5)

Javascript将this参数提供给callapply非严格模式。来自MDN

  

如果该方法是非严格模式代码中的函数,则nullundefined将替换为全局对象,并且原始值将被加框。

答案 2 :(得分:0)

其他答案提供了有关自动装箱何时发生的详细信息,但是还有两点需要记住:

    使用in运算符时,不会发生
  • 自动装箱 ,如果接收到的值不是对象,该运算符将引发TypeError。一种简单的解决方案是使用Object(value)手动将对象装箱。

  • 使用for...of或扩展语法[...value]进行迭代时,会发生某种形式的自动装箱。