分享

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

 印度阿三17 2019-09-25

Stoyan Stefanov在他的优秀书“面向对象的JavaScript”中说:

Any value that doesn’t belong to one of the five primitive types listed above is an object.

有五种原始类型,他的意思是Number,String,Boolean,Undefined和Null.但是在谷歌Chrome控制台中,数字似乎根本不是基本类型(与像int这样的C基本类型相比).看起来原始数字有方法:

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'

那么这背后的魔力是什么? JavaScript如何处理对象与原始类型?我宁愿不使用单词primitive,用简单的对象代替它.我认为那些是无法用新属性扩展的对象,但它们是通过构造函数构造的,并且还具有可以像普通对象一样扩展的原型.

解决方法:

[…] It looks like the primitive number has methods

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

考虑这个简单的例子:

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

旁注:在ES5s严格模式下,这将是一个原语,类型将是数字

由于变量num是基元,因此无法为其赋值.

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

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

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

So what is the magic behind this? How JavaScript treats objects versus primitive types?

此过程在ES5 §8.7.1 GetValue中描述

对于一个对象:

>如果Type(V)不是Reference,则返回V.
>让base成为调用GetBase(V)的结果.
>如果是IsUnresolvableReference(V),则抛出ReferenceError异常.
>如果是IsPropertyReference(V),那么

>如果HasPrimitiveBase(V)为false,则get get为base的[[Get]]内部方法,否则让get为下面定义的特殊[[Get]]内部方法.
>返回使用base作为此值调用get internal方法的结果,并为参数传递GetReferencedName(V).

>否则,base必须是环境记录.

>返回调用GetBindingValue(参见10.2.1)的结果,将getReferencedName(V)和IsStrictReference(V)作为参数传递给base.

对于原语:

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:

>让O成为ToObject(基础).
>设desc是调用属性名为P的O的[[GetProperty]]内部方法的结果.
>如果未定义desc,则返回undefined.
>如果IsDataDescriptor(desc)为true,则返回desc.[[Value]].
>否则,IsAccessorDescriptor(desc)必须为true,所以让getter为desc.[[Get]].
>如果未定义getter,则返回undefined.
>返回调用[[Call]] getter提供base的[[Call]]内部方法的结果作为此值并且不提供参数.

注意在上述方法之外无法访问可能在步骤1中创建的对象.实现可能会选择避免实际创建对象.使用此内部方法的此类实际属性访问可以具有可见效果的唯一情况是它调用访问器函数时.

[1] IsPropertyReference(V).如果基值是对象或HasPrimitiveBase(V)为true,则返回true;否则返回true.否则返回false.

来源:https://www./content-1-466651.html

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多