问题描述
在处理另一个问题时,我创造了这个小提琴:
While working on another problem, I created this fiddle:
function foo() {
// console.log(_.isBoolean(this));
console.log(this === true);
}
foo.call(true); // object:[object Boolean]
foo.apply(true); // object:[object Boolean]
这是自动装箱的一个例子吗?
Is this an example of auto-boxing?
从值类型转换为引用类型。
Going from a value type to a reference type.
这是
推荐答案
首先,我假设您正在讨论将原始值自动转换为对象。在两种情况下,这种情况发生在JavaScript中:
First of all I assume you are talking about automatic conversion of primitive values to objects. This happens in two cases in JavaScript:
- 当您将原始值作为
传递时
值为.call
或.apply
(尽管不是严格模式)。 - 当您尝试访问原始值的属性时,例如
foo bar.split()
。
- When you pass a primitive value as the
this
value to.call
or.apply
(not in strict mode though). - When you are trying to access a "property" of a primitive value, e.g.
"foo bar".split()
.
在第一种情况下转换是永久性的,即这个
确实会引用一个对象,在第二个转换只在内部进行评估期间
In the first case the conversion is permanent, i.e. this
will indeed reference an object, in the second the conversion only takes place internally for the duration of the evaluation
如果您对转换的细节不感兴趣,可以忽略其余的答案。
If you are not interested in the details of the conversion, you can ignore the rest of the answer.
的 1。原始值为此
1. Primitive value as this
当某个函数被执行且其这个时
value不是一个对象,它被转换为一个,至少在非严格模式下。 :
When a function is exectued and its this
value is not an object, it is converted to one, at least in non-strict mode. This is described in §10.4.3 Entering Function Code in the ECMAScript 5.1 documentation:
- 如果功能代码是严格代码,请设置
ThisBinding
到thisArg
。 - 否则,如果
thisArg
是null
或undefined
,将ThisBinding
设置为全局对象。 - 否则,如果
类型(thisArg)
不是对象
,请设置ThisBinding
到ToObject(thisArg
)。
[...]
- If the function code is strict code, set the
ThisBinding
tothisArg
. - Else if
thisArg
isnull
orundefined
, set theThisBinding
to the global object. - Else if
Type(thisArg)
is notObject
, set theThisBinding
toToObject(thisArg
).
[...]
正如您在第三步中看到的那样,该值将转换为一个对象ct通过调用。
As you can see in step three the value is converted to an object by calling ToObject
.
2。属性访问
当您尝试访问属性时会发生类似的事情()。这里引用的部分解释了如何计算表达式 foo [bar]
,即如何评估带括号表示法的属性访问。我们感兴趣的部分也适用于点符号。
Something similar happens when you are trying to access properties (§11.2.1 Property Accessors ). The quoted part here explains how the expression foo[bar]
is evaluated, i.e. how property access with the bracket notation is evaluated. The part we are interested in applies to dot notation as well.
- 让
baseReference
成为评估结果MemberExpression
。 - 让
baseValue
为GetValue(baseReference)
。
[...]
- Let
baseReference
be the result of evaluatingMemberExpression
. - Let
baseValue
beGetValue(baseReference)
.
[...]
  8.返回类型
的值,其 base
值为 baseValue
且其引用名称为 propertyNameString
,其严格
模式标志为 strict
。
8. Return a value of type Reference
whose base
value is baseValue
and whose referenced name is propertyNameString
, and whose strict
mode flag is strict
.
重要的一步是最后一步:无论是什么 MemberExpression
计算,它被转换为。这是一个仅在规范中使用的数据类型,包含有关如何从引用中检索实际值的其他信息(不要与实际JavaScript代码中的对象引用混淆!)。
The important step is the last one: No matter to what MemberExpression
evaluates, it is converted to a value of type Reference
. This is a datatype only used in the specification and contains additional information about how the actual value should be retrieved from the reference (not to be confused with object references in actual JavaScript code!).
要获得此类参考的真实值/结果,内部函数被调用(就像在步骤2中一样)上面的算法),其中说:
To get the "real" value/result from such a reference, the internal function GetValue(V)
(§8.7.1) is called (just like in step 2 in the above algorithm), where it says:
- 让
O
成为ToObject(base)
。
[...]
- Let
O
beToObject(base)
.
[...]
示例:
假设我们有表达式
var foo = "BAR".toLowerCase();
这是一个赋值表达式,其计算方法如下:
This is an assignment expression which is evaluated as follows:
- 让
lref
成为评估LeftHandSideExpression
的结果。 - 让
rref
成为评估AssignmentExpression
的结果。 - 让
rval
为GetValue(rref)
。
[...]
- Let
lref
be the result of evaluatingLeftHandSideExpression
. - Let
rref
be the result of evaluatingAssignmentExpression
. - Let
rval
beGetValue(rref)
.
[...]
步骤1:评估左侧,即标识符 foo
。如何解析确切的标识符对此并不重要。
步骤2:评估右侧,即BAR.toLowerCase()
。该评估的内部结果将是一个参考值,类似于:
Step 1: The left hand side is evaluated, which is the identifier foo
. How exactly identifiers are resolved is not important for this.
Step 2: The right hand side is evaluated, i.e. "BAR".toLowerCase()
. The internal result of that evaluation will be a reference value, similar to:
REFERENCE = {
base: "BAR",
propertyNameString: "toLowerCase",
strict: false
}
并存储在 rref
。
第3步:调用GetValue(rref)
。引用的 base
是值BAR
。由于这是一个原始值,因此将调用 ToObject
将其转换为临时 字符串
对象。此外,引用实际上是属性访问,因此 GetValue
最终将调用方法 toLowerCase
在 String
对象上并返回方法的结果。
Step 3: GetValue(rref)
is called. The base
of the reference is the value "BAR"
. Since this is a primitive value, ToObject
will be called to convert it to a temporary String
object. Furthermore, the reference is actually a property access, so GetValue
will eventually call the method toLowerCase
on the String
object and return the method's result.
这篇关于javascript autobox?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!