JavaScript 对象类型和基本类型有什么区别?

2024-03-20

Stoyan Stefanov 在他的优秀著作《面向对象的 JavaScript》中说道:

任何不属于上面列出的五种基本类型之一的值都是对象。

对于五种原始类型,他的意思是Number, String, Boolean, Undefined and Null。然而,在 Google Chrome 控制台中,数字似乎根本不是原始类型(与C原始类型如int)。它看起来像原始number 有方法:

var a = 2.2;
console.log(a.toFixed()); // logs "2"

因此,我假设我可以像处理对象一样处理数字,因此我尝试为其分配一个属性:

var a = 2;
a.foo = 'bar';
console.log(a.foo); // logs undefined

我不明白这种行为。如果 number 有方法,它的行为应该像对象,不是吗?它甚至还有一个原型:

Number.prototype.foo = 'bar';
var a = 2;
console.log(a.foo); // logs 'bar'

那么什么是magic这背后? JavaScript 如何对待对象原始类型?我宁愿不使用这个词原始并将其替换为简单的物体。在我看来,这些对象无法使用新属性进行扩展,但是它们是通过构造函数构造的,并且还具有可以像普通对象一样扩展的原型。


[...] 它好像原始数有方法

原始的,实际上并没有自己的属性。它被强制为一个对象,以便能够访问“它的”属性。强制对象在调用方法之外不可访问*(在严格模式下,即使not在方法内)*。因此,引用的变量始终是原语。

考虑这个简单的例子:

Number.prototype.myTypeInAMethod = function () {
   console.log (typeof this.valueOf ()) //"number" => The primitive is wrapped in an object. 
   return typeof this;
}

var num = 123;
typeof num; //number
num.myTypeInAMethod () //object

side note: In ES5s strict mode,this would be a primitive and the type would be number

由于变量num是一个原始的,你可以not为其赋值。

num.foo = "bar";
num.foo //undefined

如果您创建一个数字(或字符串)通过它的对象构造函数,它的类型确实是一个对象。 通过添加属性进行快速检查表明它实际上可以被分配。

var objNum = new Number(123);
typeof objNum ; //"object"
objNum.foo = "bar";
objNum.foo //"bar"

那么这背后有何魔力呢? JavaScript 如何处理对象和原始类型?

这个过程描述于ES5 §8.7.1 http://es5.github.io/#x8.7.1 GetValue

对于一个对象:

  • If Type(V)不是引用,返回V.
  • 令base为调用的结果GetBase(V).
  • If IsUnresolvableReference(V),抛出一个参考错误例外。
  • If IsPropertyReference(V), then
    • If HasPrimitiveBase(V) is false,然后让get是 [[Get]] 内部方法base,否则让get是下面定义的特殊 [[Get]] 内部方法。
    • 返回调用结果get内部方法使用base as its this值,并通过GetReferencedName(V)为了论证。
  • Else, base must be an environment record.
    • 返回调用结果GetBindingValue (see 10.2.1 http://es5.github.io/#x10.2.1)具体方法base通过GetReferencedName(V) and IsStrictReference(V)作为参数。

对于原语:

The following [[Get]] internal method is used by GetValue when V is a property reference[1] with a primitive base value. It is called using base as its this value and with property P as its argument. The following steps are taken:

  • Let O be ToObject(base).
  • Let desc是调用 [[GetProperty]] 内部方法的结果O带有属性名称P.
  • If desc is 不明确的, 返回不明确的.
  • If IsDataDescriptor(desc) is true, 返回desc。[[价值]]。
  • 否则,IsAccessorDescriptor(desc)必须是true所以让getter be desc。[[得到]]。
  • If getter is 不明确的, 返回不明确的.
  • 返回调用[[Call]]内部方法的结果getter提供base as the this值并且不提供任何参数。

NOTE The object that may be created in step 1 is not accessible outside of the above method. An implementation might choose to avoid the actual creation of the object. The only situation where such an actual property access that uses this internal method can have visible effect is when it invokes an accessor function.

[1] IsPropertyReference(V)。退货true如果基值是一个对象或者HasPrimitiveBase(V) is true;否则返回false.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JavaScript 对象类型和基本类型有什么区别? 的相关文章

随机推荐