Does javascript autobox?

Does javascript autobox?

本文关键字:autobox javascript Does      更新时间:2023-09-26

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

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]

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

从值类型转换为引用类型

这是维基百科的定义

首先我假设你在谈论原始值到对象的自动转换。在JavaScript中有两种情况:

  1. 当您将原始值作为this值传递给.call.apply时(虽然不是严格模式)。
  2. 当您试图访问原始值的"属性"时,例如"foo bar".split()

在第一种情况下,转换是永久的,即this将确实引用一个对象,在第二种情况下,转换仅在

求值期间在内部进行。

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


1。原语值为this

当一个函数被执行并且它的this值不是对象时,它被转换为对象,至少在非严格模式下是这样。这在ECMAScript 5.1文档中的§10.4.3输入函数码[spec]中有描述:

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

  1. 如果功能码为严格码,则设置ThisBindingthisArg
  2. 如果thisArgnullundefined,则设置ThisBinding为全局对象
  3. 如果Type(thisArg)不是Object,则设置ThisBindingToObject(thisArg)
    […]
在第三步中可以看到,通过调用ToObject [spec]将值转换为对象。

2。属性访问

当你试图访问属性(§11.2.1 Property Accessors [spec])时,也会发生类似的情况。这里用引号括起来的部分解释了表达式foo[bar]是如何求值的,即如何用括号表示的属性访问进行求值。我们感兴趣的部分也适用于点表示法。

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

  1. baseReferenceMemberExpression的求值结果
  2. baseValueGetValue(baseReference)
    […)

,,8. 返回类型为Reference的值,其base值为baseValue,引用名称为propertyNameString, strict模式标志为strict

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

为了从这样的引用中获得"真实"的值/结果,调用内部函数GetValue(V)(§8.7.1)[spec](就像上面算法的第2步一样),其中它说:

V是具有基本基值的属性引用时,GetValue使用以下[[Get]]内部方法。使用base作为其this值,并使用属性P作为其参数来调用它。执行以下步骤:

  1. OToObject(base)
    […]

例子:

假设我们有表达式

var foo = "BAR".toLowerCase();

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

产品AssignmentExpression : LeftHandSideExpression = AssignmentExpression的评估如下:

  1. lrefLeftHandSideExpression的求值结果。
  2. rrefAssignmentExpression的求值结果
  3. rvalGetValue(rref)
    […]

步骤1:计算左侧,即标识符foo。标识符的解析方式并不重要。
步骤2:计算右侧,即"BAR".toLowerCase()。该计算的内部结果将是一个参考值,类似于:

REFERENCE = {
    base: "BAR",
    propertyNameString: "toLowerCase",
    strict: false
}

保存在rref .

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

Javascript将非严格模式下提供给callapplythis参数框起来。从MDN:

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

其他答案提供了自动装箱何时发生的详细信息,但这里还有一些事情需要记住:

  • 当使用in操作符时,自动装箱不会发生,如果收到的值不是对象,则会抛出TypeError。一个简单的解决方案是用Object(value)手动将对象框起来。

  • 当使用for...of或扩展语法[...value]进行迭代时,会出现某种形式的自动装箱,这允许对字符串进行迭代。