第一次翻译,可能有不少地方不恰当,欢迎指正。javascript
原文地址:http://javascriptweblog.wordpress.com/2010/09/27/the-secret-life-of-javascript-primitives/java
你可能不知道,在javascript中,在使用string, number, 布尔类型这些原始值时,都会遇到意想不到的问题。阅读下文,来揭晓里面的秘密。web
对象就是各个属性的集合,属性能够是对一个对象的引用或是一个原始值,原始值是一个值,他们没有属性。wordpress
在 JS 里的五类原始类型是:undefined, null, boolean, string 和 number."其他"的类型都是对象.其中 boolean, string 和 number 原始类型能够被对应的对象类型包裹.这些对象都应该是 Boolean, String 和 Number 类的实例。this
typeof true; //"boolean" typeof Boolean(true); //"boolean" typeof new Boolean(true); //"object" typeof (new Boolean(true)).valueOf(); //"boolean" typeof "abc"; //"string" typeof String("abc"); //"string" typeof new String("abc"); //"object" typeof (new String("abc")).valueOf(); //"string" typeof 123; //"number" typeof Number(123); //"number" typeof new Number(123); //"object" typeof (new Number(123)).valueOf(); //"number"
由于javascript在原始值与对象之间很轻松的互换类型。在这种状况下,为了获得length属性,字符串的value值就被强制转换为字符串对象。String对象仅仅是被瞬间转换,而后会被当着垃圾回收处理掉。对于这种现象,咱们先避开这个难解的谜团,接下来慢慢分析它。prototype
String.prototype.returnMe= function() { return this; } var a = "abc"; var b = a.returnMe(); a; //"abc" typeof a; //"string" (still a primitive) b; //"abc" typeof b; //"object"
可是你会发现,只要这个对象还存在,这个对象不会被当着垃圾回收来处理。翻译
在strict模式下,这种现象不会出现。指针
这里有一个典型的实例来解释这个对象没有被当着垃圾回收来处理掉。code
Number.prototype.toString = function() { return typeof this; } (123).toString(); //"object"
也就是说原始值是有属性的(包括方法),这些属性是他们各自的原型所定义的。对象
是的,大多数状况下,对象仅仅是容器,value是他们包含的原始值,他们会按需的强制性转换为对应的value值。来看下面的实例:
//object coerced to primitive var Twelve = new Number(12); var fifteen = Twelve + 3; fifteen; //15 typeof fifteen; //"number" (primitive) typeof Twelve; //"object"; (still object) //another object coerced to primitive new String("hippo") + "potamus"; //"hippopotamus" //object not coerced (because 'typeof' operator can work with objects) typeof new String("hippo") + "potamus"; //"objectpotamus"
奇怪的是boolean 对象不会被轻易的转换,除了遇到null 与undefined, boolean 对象都会自动修正为true,试试这个:
if (new Boolean(false)) { alert("true???"); }
一般你可能想清楚的知道boolean 对象的value值,下面的作法能明确的判定value值是true,仍是false
var a = ""; new Boolean(a).valueOf(); //false
可是,这样作可能更容易些:
var a = Boolean(""); a; //false
甚至是这样:
var a = ""; !!a; //false
答案是no
var primitive = "september"; primitive.vowels = 3; primitive.vowels; //undefined;
若是javascript探测到试图对一个原始值赋值,事实上它会强制把这个原始值转换为对象,可是,正如上面的实例,这个新对象是没有指针的,会马上被回收处理掉。
这里有个伪代码实例来解释这种现象:
var primitive = "september"; primitive.vowels = 3; //new object created to set property (new String("september")).vowels = 3; primitive.vowels; //another new object created to retrieve property (new String("september")).vowels; //undefined
正如你看到的,这种写法不只无效,并且是至关的浪费。
最后证实相对于对原始值赋值,给对象赋值是它的一个惟一优点。可是在实践中,这种作法也是可疑的。Strings, booleans 与numbers有着特定的,定义好的用途。从新定义他们偏偏让人难以理解。并且,原始值是不可变的,你不可能经过改变他们的属性值来修改他们。
var me = new String("Angus"); me.length = 2; //(error in strict mode) me.length; //5 (not 2 - thanks @joseanpg) me.valueOf(); "Angus"
并且,我认为对原始值深入的理解,以及当使用他们的时候知道具体发生了什么是深刻理解这门语言迈出重要的一步。