英文:
ToPrimitive VS OrdinaryToPrimitive
问题
我正在阅读Kyle Simpson的《YDKJS》中的关于强制类型转换的部分。在查看规范时,我发现ToPrimitive有条件地调用OrdinaryToPrimitive。我在一个博客中看到:
JavaScript将具有[Symbol.ToPrimitive]方法的对象视为奇异的,奇异的exoticToPrim属性变得已定义
这意味着如果对象的exoticToPrim属性未定义,将调用OrdinaryToPrimitive。
示例:
- var a = 42;
- a + " ";
- String(a);
我的疑问(强制类型转换在底层如何工作):
- 基本值'a'会在连接时被动态包装成Number对象吗?
- 在第2行传递的提示将是默认的(即Number),但在第3行,它将是字符串。提示仅在显式转换时传递吗?
- 在强制类型转换期间是否会调用OrdinaryToPrimitive?由于Number.prototype不包含方法Symbol.toPrimitive(因为*Reflect.ownKeys(Array.prototype)*不返回Symbol.toPrimitive),因此exoticToPrim将为未定义。即使对于其他对象(如Array.prototype不包含此方法),似乎也是如此,根据规范7.1.1,仅为自定义奇异对象(覆盖了Symbol.Primitive的对象)执行1a和1b。
注意:我知道什么是抽象操作,并且引擎会自行定义它们,我们不能显式调用它们(尽管可以覆盖它们)。
更新
以下是他的书中的摘录:
然后他说:
英文:
I am reading the Book, YDKJS by Kyle Simpson, topic Coercion. While looking at the specs I found that ToPrimitive calls OrdinaryToPrimitive conditionally. I read in a blog that:
> JavaScript view objects with [Symbol.ToPrimitive] method as exotic and the exoticToPrim property become defined
That means if the exoticToPrim property for an object is undefined, OrdinaryToPrimitive is called.
Example:
1. var a = 42;
2. a + " ";
3. String(a);
My Queries (How Coercion working under the Hood) :
- Primitive value 'a' will somewhere be boxed to Number object on fly for the sake of concatenation?
- Hint passed in Line 2 will be default(i.e. Number) but in line 3, it will be string. Hint is passed only for explicit conversion?
- Will OrdinaryToPrimitive be called during coercion? Since Number.prototype doesn't contain method, Symbol.toPrimitive (Because Reflect.ownKeys(Array.prototype) doesn't return Symbol.toPrimitive), hence exoticToPrim would be undefined. And even for other objects (such as Array.prototype doesn't contain this method) so it seems like, as per spec 7.1.1 1a and 1b are executed only for custom exotic objects (the one which overrides Symbol.Primitive).
Note: I know what Abstract Operations are and that engines define them on their own and that we can't call them explicitly (though override them)
UPDATED
Following is an excerpt from his Book:
He then says:
答案1
得分: 2
Here are the translations of the provided text:
-
原始值 'a' 将会在拼接时被隐式转换为 Number 对象吗?
不会。您错过了[Symbol.toPrimitive]
属性仅适用于对象。您可以看到第一次操作ToPrimitive是检查"如果input
是一个对象"。
所以这根本不适用。不会发生装箱,不会调用任何方法。原始值42
将立即从ToPrimitive返回。然后它被传递给ToString操作,因为+
的另一个操作数是字符串。 -
提示仅在显式转换时传递吗?
您可以轻松检查规范,查看所有调用ToPrimtive的地方。一般情况下,会传递提示,我找到的唯一没有传递提示的地方是+
运算符,将对象与原始值比较时的==
/!=
运算符,以及在使用单个参数(不是Date
对象)调用new Date
时。 -
在强制转换期间是否会调用
OrdinaryToPrimitive
?
不会。使用String()
函数进行强制转换会直接调用(除了符号)ToString操作,该操作再次不会在非对象上使用ToPrimitive(或OrdinaryToPrimitive)。对于数字,它会直接分派到数字到字符串操作。
英文:
> Primitive value 'a' will somewhere be boxed to Number object on fly for the sake of concatenation?
No. You missed that the [Symbol.toPrimitive]
property only applies to objects. You can see that the first operation ToPrimitive does is to check "If input
is an Object".
So this doesn't apply at all. No boxing happens, no methods are called. The primitive value 42
is immediately returned back from ToPrimitive. It is then passed to the ToString operation since the other operand of +
is a string.
> Hint is passed only for explicit conversion?
You can easily check the spec for all places where ToPrimtive is called. In general, a hint will be passed, the only places I found where none is passed are the +
operator, the ==
/!=
operators when comparing an object to a primitive value, and weirdly when calling new Date
with a single argument (that is not a Date
object).
> Will OrdinaryToPrimitive
be called during coercion?
No. Coercion using the String()
function directly calls (except for symbols) the ToString operation which does, again, not use ToPrimitive (or OrdinaryToPrimitive) on non-objects. Instead, for numbers it directly dispatches to the number-to-string operation.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论