问题描述
在 JavaScript 中,原始类型(数字、字符串等)不是对象。因此,它们没有 [[prototype]] 因此不能使用某些对象的 [[prototype]] 中可用的方法。
而 Number、String 是包装对象,可用于通过 new
关键字创建变量,我们可以在这些变量上使用 Number 对象原型中可用的方法(使用 new
关键字)。
但在给定的代码中,我创建了一个原始类型变量,并且能够使用诸如 toFixed()
之类的方法,它驻留在 Number 对象中。
这让我很困惑。请详细说明这一点。
let a = 6.678; //primitive type
a= a.toFixed(1); // toFixed() resides in prototype of Number Object
console.log(a); // 6.7
解决方法
这与称为“自动装箱”的概念有关,Javascript 看到您正在尝试访问原始类型的属性,因此在运行时的一小段时间内,它会将原始值转换为其相应的包装对象并继续进行属性调用,然后在大多数情况下将值转换回原始类型。
let a = 6.678; //primitive type
a= a.toFixed(1); // JS converts a to "Number Object" and then the function is called
console.log(a); // 6.7
这是一个很好的答案Does javascript autobox?
,这就是 JavaScript 引擎或多或少的工作方式。您是正确的,您分配给 a
的变量是 Number 类型的原始值,但是当您访问此原始值的方法时,JS 将创建一个特殊的包装对象(它将为每个原始值执行此操作)类型,即字符串)并允许它访问这些方法。
在您访问该方法后,该值将不再是一个对象。
您可以在此处阅读更多相关信息: https://javascript.info/primitives-methods#a-primitive-as-an-object
@ashu 在下面的回答中包含了我实际上并不知道的技术术语 - 所以 TIL!显然,这就是所谓的“自动装箱”!
,由于 thisNumberValue 抽象操作,我们能够执行 toFixed() 操作,它检查 Type(value) 是 Number 返回值,否则如果 Type(value) 是 Object 并且 value 有 [[NumberData]]内部插槽,然后让 n 为值并分配 Type[n] 为 Number。返回值,否则抛出 TypeError
异常。
根据 ECMAScript® 2020 Language Specification
Number.prototype.toFixed (fractionDigits)
toFixed
返回一个包含此 Number 值的字符串,以十进制定点表示法表示,小数点后带有 fractionDigits 位。如果fractionDigits 未定义,则假定为0。
执行 toFixed() 操作时执行以下步骤:
- 设 x 为 ?
thisNumberValue(this value)
。
注意
抽象操作 thisNumberValue
(value) 执行以下步骤:
-
如果
Type(value)
是数字,则返回值。 -
如果 Type(value) 是 Object 并且 value 有一个 [[NumberData]] 内部 插槽,然后
- 设 n 为值。[[NumberData]]。
- 断言:Type(n) 是数字。
- 返回 n。
-
抛出 TypeError 异常。
- 让 f 是?
ToInteger(fractionDigits)
。
注意 抽象操作ToInteger
将参数转换为整数值。此抽象操作的功能如下:
- 让数字是?
ToNumber(argument)
。 (注意 ToNumber 也是一个抽象操作) - 如果数字为 NaN,则返回 +0。
- 如果数字是 +0、-0、+∞ 或 -∞,则返回数字。
- 返回数值 与数字同号,大小为 floor(abs(number)).
- 断言:如果
fractionDigits
未定义,则 f 为 0。