基元和对象

时间:2013-01-18 20:44:11

标签: javascript

David Flanagan的最终JavaScript区分对象和基元。

他将基元定义为Number,String,Boolean,Null和Undefined,标准也是如此。

但是,定义一个原语作为对象的子集,即将它们称为原始对象,会更准确吗?

因为他们有自己的方法并且是复杂的实体。

实际问题

在定义String,Boolean和Number时,原始对象会比Object更准确吗?

3 个答案:

答案 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表明访问者属性应该是评估如下:

  
      
  1. 让baseReference成为评估MemberExpression的结果。
  2.   
  3. 让baseValue为GetValue baseReference )。
  4.         

    (...)

然后在8.7.1中我们看到以下内容:

  

V 是一个时,GetValue使用以下[[Get]]内部方法   具有原始 base 值的属性引用。它被称为使用   base为this值,属性为 P 。该   采取以下步骤:

     
      
  1. 设O为ToObject(base)。
  2.   
  3. 让desc成为调用的结果   [[GetProperty]] O的内部方法,属性名称为P.
  4.   
  5. 如果是,那就是   undefined,返回undefined。
  6.   
  7. 如果IsDataDescriptor(desc)为true,则返回   描述第[[值]]。
  8.   
  9. 否则,IsAccessorDescriptor(desc)必须为true,
  10.   
  11. 让getter成为desc。[[Get]]。如果未定义getter,则返回undefined。
  12.   
  13. 返回调用getter的[[Call]]内部方法的结果   提供base作为此值并且不提供参数。
  14.         

    注意   可能在步骤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]+组成的符号。