- 在js中
null
是关键字,而undefined
只是一个普通的标识符,并且是一个全局属性,这意味着它的值可以被修改 - 可以使用
void 0
去安全得获取undefined
- js中唯一不等于自身的值
- BigInt 并不是
===
有着相同数学值的 Number,而是==
相等
- js中除了
Object
,其他均为原始值
路径一: 原始值强制转换:ToPrimitive("default")
→ valueOf()
→ toString()
- 原始值强制转换用于得到一个期望的原始值,但对实际类型应该是什么并没有强烈的偏好
- 只有
Date()
传入Object时会走该路径(暂不确定,v8源码中只有Date的构造函数未传入hint
)
路径二:数字类型强制转换、number 类型强制转换、BigInt 类型强制转换ToPrimitive("number")
→ valueOf()
→ toString()
路径三:字符串类型强制转换:ToPrimitive("string")
→ toString()
→ valueOf()
-
ToPrimitive(input, PreferredType)
:- 如果输入值
input
的类型是对象,根据以下步骤进行转换:- 如果没有指定
PreferredType
,则将hint
设置为 "default"。 - 如果
PreferredType
是字符串类型,则将hint
设置为 "string"。 - 如果
PreferredType
是数字类型,则将hint
设置为 "number"。 - 检查对象是否定义了
@@toPrimitive
方法,如果是,则调用该方法并传递hint
作为参数,将返回值作为结果,如果未定义就使用OrdinaryToPrimitive
(见下文)。 - 如果返回的结果不是对象类型,直接返回该结果。
- 否则,抛出 TypeError 异常。
- 如果没有指定
- 如果输入值的类型不是对象,则直接返回该值。
- 如果输入值
-
OrdinaryToPrimitive(input, hint)
:- 当使用参数
input
和hint
调用OrdinaryToPrimitive
时,执行以下步骤:- 如果
hint
是 "string",则按照顺序尝试调用对象的toString()
和valueOf()
方法。 - 否则,按照顺序尝试调用对象的
valueOf()
和toString()
方法。 - 对于每个方法名按顺序执行以下步骤:
- 令
method
为从对象input
中获取的方法。 - 如果
method
是可调用的,则调用该方法并将对象input
作为上下文。 - 如果调用结果的类型不是对象,则直接返回该结果。
- 令
- 抛出 TypeError 异常。
- 如果
- 当使用参数
- 只有
Date
和Symbol
类型有[@@toPrimitive]
方法Date.prototyp[@@toPrimitive]
将hint
的"default"
视为"string"
并且调用toString()
而不是valueOf()
Symbol.prototype[@@toPrimitive]
忽略hint
,并总是返回一个symbol
@@toPrimitive
如果存在,必须返回原始值,否则会报错TypeError
MaybeHandle<Object> JSReceiver::ToPrimitive(Isolate* isolate,
Handle<JSReceiver> receiver,
ToPrimitiveHint hint) {
Handle<Object> exotic_to_prim;
ASSIGN_RETURN_ON_EXCEPTION(
isolate, exotic_to_prim,
Object::GetMethod(isolate, receiver,
isolate->factory()->to_primitive_symbol()),
Object);
if (!IsUndefined(*exotic_to_prim, isolate)) {
Handle<Object> hint_string =
isolate->factory()->ToPrimitiveHintString(hint);
Handle<Object> result;
ASSIGN_RETURN_ON_EXCEPTION(
isolate, result,
Execution::Call(isolate, exotic_to_prim, receiver, 1, &hint_string),
Object);
if (IsPrimitive(*result)) return result;
THROW_NEW_ERROR(isolate,
NewTypeError(MessageTemplate::kCannotConvertToPrimitive),
Object);
}
return OrdinaryToPrimitive(isolate, receiver,
(hint == ToPrimitiveHint::kString)
? OrdinaryToPrimitiveHint::kString
: OrdinaryToPrimitiveHint::kNumber);
}
逻辑说明:
- 获取
receiver
对象中的to_primitive_symbol
方法。- 如果存在
to_primitive_symbol
方法,则调用该方法并返回结果。- 如果不存在
to_primitive_symbol
方法,则调用OrdinaryToPrimitive
方法进行转换,并返回转换后的结果。
// v8/src/init/bootstrapper.cc
// Install the @@toPrimitive function at Symbol.
InstallFunctionAtSymbol(
isolate_, prototype, factory->to_primitive_symbol(),
"[Symbol.toPrimitive]", Builtin::kSymbolPrototypeToPrimitive, 1, true,
static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY));
// Install the @@toPrimitive function at Date.
InstallFunctionAtSymbol(
isolate_, prototype, factory->to_primitive_symbol(),
"[Symbol.toPrimitive]", Builtin::kDatePrototypeToPrimitive, 1, true,
static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY));