第一次翻譯,可能有不少地方不恰當,歡迎指正。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"
並且,我認爲對原始值深入的理解,以及當使用他們的時候知道具體發生了什麼是深刻理解這門語言邁出重要的一步。