David Flanagan的最终JavaScript区分对象和基元。
他将基元定义为Number,String,Boolean,Null和Undefined,标准也是如此。
但是,定义一个原语作为对象的子集,即将它们称为原始对象,会更准确吗?
因为他们有自己的方法并且是复杂的实体。
实际问题
在定义String,Boolean和Number时,原始对象会比Object更准确吗?
答案 0 :(得分:3)
对象和原语是截然不同的:
typeof 42 === "number"
typeof new Number(42) === "object"
new Number(42) !== 42
但是,必要时,基元会被临时对象自动包裹,可以是automatically converted back into primitives:
(42).toString() === "42"
new Number(42) == 42
new Number(42) + 1 === 43
特别是在Java和C#编程语言的上下文中,这种行为称为autoboxing。由于包装器对象具有一些令人困惑的特性,例如:
Boolean(new Boolean(false)) === true
在变量中avoid intentionally storing them是一种好习惯,而是尽可能使用原语。
答案 1 :(得分:2)
这不是语义,看:
var threePrimitive = 3;
var threeObject = new Number(3);
threePrimitive.toFixed(2); // 3.00
threeObject.toFixed(2); // 3.00
threePrimitive.foo = true
threeObject.foo = true;
threePrimitive.foo; // undefined
threeObject.foo; // true
当您尝试在对象上调用方法时,基元会被包装在对象中,但在初次使用后,该对象将被丢弃。
至于如何在规范中说明,我不是100%肯定,但这是我的想法(基于tips left by Bergi in one of his answers。章节11.2.1表明访问者属性应该是评估如下:
- 让baseReference成为评估MemberExpression的结果。
- 让baseValue为
醇>GetValue
( baseReference )。(...)
然后在8.7.1中我们看到以下内容:
当 V 是一个时,GetValue使用以下[[Get]]内部方法 具有原始 base 值的属性引用。它被称为使用 base为
this
值,属性为 P 。该 采取以下步骤:
- 设O为ToObject(base)。
- 让desc成为调用的结果 [[GetProperty]] O的内部方法,属性名称为P.
- 如果是,那就是 undefined,返回undefined。
- 如果IsDataDescriptor(desc)为true,则返回 描述第[[值]]。
- 否则,IsAccessorDescriptor(desc)必须为true,
- 让getter成为desc。[[Get]]。如果未定义getter,则返回undefined。
- 返回调用getter的[[Call]]内部方法的结果 提供base作为此值并且不提供参数。
醇>注意 可能在步骤1中创建的对象无法访问 以上方法。实现可能会选择避免实际 创建对象。这种实际的唯一情况 使用此内部方法的属性访问可以产生可见效果 就是它调用一个访问函数。
答案 2 :(得分:1)
原始对象在定义时是否比对象更准确 String,Boolean和Number?
请注意,我并不是说这里的数字不是对象,我指出它显示含糊不清。这种混淆JavaScript新手的事情。
区别主要是学术性的,但有一种情况似乎含糊不清:文字代表原始对象,除非文字似乎代表一个数字。您不能将方法直接应用于文字整数*符号:
1.toString();
SyntaxError: identifier starts immediately after numeric literal
...但您可以应用数字方法:
Number(1).toString();
'1'
...并且包含数字的名称是数字:
x = 4;
x.toString();
'4'
我认为这实际上是一个解析问题,但我真的不知道为什么解析器不能告诉1
是一个数字就像它可以告诉“abc”是一个字符串一样容易。我想它与.
符号的语义歧义有关。 (它是小数点还是方法运算符?)
* JavaScript实际上没有整数。我只是指一个完全由[0-9]+
组成的符号。