两种变量创建类型的异同


我们知道,javascript中,除了null、undefined两种类型,一切都是对象。然而:


 javascript


 var num_obj = new Number(100);
var num_val = 100;

console.log(typeof num_obj); // "object"
console.log(typeof num_val); // "number"

num_obj.myCustomAttr = "my custom attrbute";
num_val.myCustomAttr = "my custom attrbute";

console.log(num_obj.myCustomAttr); // "my custom attrbute"
console.log(num_val.myCustomAttr); // undefined

那么问题来了

  1. 通过 new 关键字构造的变量与直接赋值的变量有何不同?

  2. 分别出现上述两种不同结果的原因是什么?javascript为何要这么设计?

oop string JavaScript

狂战拯救世界 11 years, 8 months ago
  1. 是typeof不是type of
  2. var num_val = 100;
    typeof num_val返回的是"number"不是"string"
    请问题主你用的什么测试的?
小姐、请自重 answered 11 years, 8 months ago

@mcfog 最后说的对,我再补充一下。题主先理解一下javascript的基本包装类型。

说一下属性赋值

num_obj.myCustomAttr = "my custom attrbute" ,这个为什么能赋值并且能读出来?因为这个num_obj存在于整个上下文中,直到页面关闭,内存清空。
num_val.myCustomAttr = "my custom attrbute" ,js在执行这段话的时候,会 new Number ()出 num_val 这个对象,然后执行属性的添加,最后再执行 num_val = null ;( 这里是js后台自动执行,也是关键所在。 )

说一下取值

前者为什么能读取我就不解释了。
在执行 console.log(num_val.myCustomAttr) ,也是先 new Number() num_val 这个对象,然后去找 myCustomAttr 这个属性,因为这个属性不是继承自父类的,没找到,返回undefined。

总的来说,基本包装类型在后台是自动new成对象的,而且这个对象是临时性的,因为最后是null掉的。
我解释的可能有点乱,没看懂的话联系我。。

GEAR3 answered 11 years, 8 months ago

补充关于装箱机制,问题中


 num_val.myCustomAttr = "my custom attrbute";
console.log(num_val.myCustomAttr);//undefined

的细节

这段代码大致相当于


 new Number(num_val).myCustomAttr = "my custom attrbute";//虽然赋值成功,但包装后的Number对象没有引用,直接被抛弃
console.log(new Number(num_val).myCustomAttr);//undefined

给我一斤蜜饯 answered 11 years, 8 months ago

我记得在JavaScript中,字符串是基本数据类型,单就你给基本数据类型这个赋值操作本身就是错的。同过new String构造方法会得到一个字符串类对象。所以typeof取到的是object。跟他进行赋值操作,肯定是可以成功的。

然后回答一下性能上的问题,直接赋值字符串,性能更好。

为什么要这么设计:我只能说。大部分oo的语言都有装箱和拆箱设计。

被诅咒的小狐狸 answered 11 years, 8 months ago

包装对象带有一些有用的属性和方法。比如,数字对象就带有toFixed()和toExponential()之类的方法,字符串对象带有substring()、chatAt()和toLowerCase()等方法以及length属性。这些方法非常方便,和原始值相比,这是包装对象的优势,但其实原始值也可以调用这些方法,因为原始值会首先转换为一个临时对象,如果转换成功,则调用包装对象的方法。

因为原始值可以根据需要转换成对象,这样的话,也不必为了用包装对象的方法而将原始值手动“包装”成对象。比如,不必使用new String("hi"),直接使用"hi"即可。
不得不使用包装对象的一个场景是,有时我们需要对值进行扩充并保持值的状态。原始值毕竟不是对象,不能直接对其进行扩充。

Source: 第三章 字面量和构造函数

乖乖缺德人 answered 11 years, 8 months ago

JavaScript 并非所有的东西都是对象


javascript 有 2 套类型系统:原始值(primitive)和对象(object)。

原始值类型 boolean, number 以及 string 都有自己对应的包装类型 Boolean, Number 和 String。

原始值是不可变的,你不能给它们添加属性

你的问题1:

通过 new 关键字构造的字符串变量与直接赋值的字符串变量有何不同?

  • new 创建的是 String 对象(object)。
  • 直接赋值的字符串变量创建的是字符串原始值(primitive)。

分别出现上述两种不同结果的原因是什么?

原始值是不可变的,你不能给它们添加属性。因此输出 undefined

javascript为何要这么设计?

不能怪 javascript,大部分语言都这样,都有 2 套类型系统。

但是现在的主流脚本语言正在改变这个现状, 一切都是对象

因此,你不仅可以写 "abcde".length() ,你甚至可以写 1.add(3) 表示 1+3 ,如果结合闭包,那就更炫酷了:


 5.time({print("hello");});

输出 5 "hello"

咸鱼型杏子茶 answered 11 years, 8 months ago

Your Answer