2011-07-22 14 views
16

可以使用typeof來確定值是原始的還是盒裝的。無論價值是原始的還是盒裝的

考慮:

typeof "foo"; // "string" 
typeof new String("foo"); // "object" 

在結合Object.prototype.toString我們可以定義以下兩種功能

var toString = Object.prototype.toString; 

var is_primitive_string = function(s) { 
    return toString.call(s) === "[object String]" && typeof s === "string"; 
}; 

var is_boxed_string = function(s) { 
    return toString.call(s) === "[object String]" && typeof s === "object"; 
}; 

是否有任何使用情況這兩個功能呢? (或者對於NumberBoolean等的類似功能)。

這個問題背後的概念來自以下Comment by T.J.Crowder

我們應該關心我們的價值是原始的還是盒裝的?

回答

7

我會說有幾乎沒有意義,你幾乎從不關心你是在處理一個string原語還是一個String對象。

有邊緣情況。例如,String對象是一個實際的對象,您可以爲其添加屬性。這讓你做這樣的事情:

function test(arg) { 
    arg.foo = "bar"; 
} 

如果調用代碼通過在string原始

var s1 = "str"; 
test(s1); 

... arg被晉升爲String對象,並得到一個屬性添加到它,但test返回後,String對象沒有被任何東西使用。

相反,如果調用代碼通過在String對象

var s2 = new String("str"); 
test(s2); 

...然後將屬性添加到該對象並調用代碼可以看到它。考慮(live copy):

var s1, s2; 

s1 = "str"; 

display("[Before] typeof s1.foo = " + typeof s1.foo); 
test(s1); 
display("[After] typeof s1.foo = " + typeof s1.foo); 

s2 = new String("str"); 

display("[Before] typeof s2.foo = " + typeof s2.foo); 
test(s2); 
display("[After] typeof s2.foo = " + typeof s2.foo); 

function test(arg) { 
    arg.foo = "bar"; 
} 

輸出:

[Before] typeof s1.foo = undefined 
[After] typeof s1.foo = undefined 
[Before] typeof s2.foo = undefined 
[After] typeof s2.foo = string

注意s2.foo是一個字符串,但s1.foo不是(因爲s1是一個字符串原始,當我們促進它創建的對象在test與調用代碼無關)。

有沒有這方面的用例?不知道。如果是這樣,我會說這將是一個非常前衛的案例。

+0

與基元相比,盒裝值「通過引用傳遞」這一事實可能會帶來一些有趣的結果。 – Raynos

+1

@Raynos,會有什麼後果?基元是不可變的,因此基元的傳遞值和傳遞參考值之間應該沒有明顯的差異。我不認爲有任何程序可以編寫,可以檢測是否所有的「真」都作爲對位於單個內存位置(如在Rhino中)的不可變對象的引用傳遞,並且它是標記的聯合這是在大多數其他口譯員中複製的。 –

3

所有的toString東西似乎是一個嘗試解決不同的內置String構造函數的跨幀混合問題。對於檢查某些東西是否是原始字符串,這是不必要的 - typeof就足夠了,因此is_primitive_string沒有用例。

我很少看到的String情況下傳遞的參數,所以我不明白爲什麼我需要檢查的東西是否是String實例跨框架,而不是僅僅通過("" + s)String(s)強迫到String值。我唯一需要在生產代碼中使用String值的時候,我需要一個空的字符串,這在某些highly optimized code中是真的。

就其他人而言,Boolean類的實例在條件中的行爲並不像人們預期的那樣。

if (new Boolean(false)) { 
    alert("WTF!"); 
} else { 
    alert("OK"); 
} 

Boolean.prototype.not = function() { return !this; }; 

if (new Boolean(false).not()) { 
    alert("OK"); 
} else { 
    alert("Really, WTF!"); 
} 

if (false.not()) { // Autoboxing 
    alert("OK"); 
} else { 
    alert("Cmon, WTF!"); 
} 

!(false)true,但是當你用創建Boolean類的實例,該!操作適用於對象的值,而對象的值總是truthy。

相信的EcmaScript 5嚴格模式正在發生變化,提出this所以最後一個例子(false.not())將表現爲當"use strict";被添加到Boolean.prototype.not在有效ES5解釋最上面的一個可能會天真地期望的那樣。

隨着Number S,使用<比較是確定,除了和其他運營商往往會按預期運行。 new Number(0)new Number(NaN)有同樣的問題圍繞條件new Boolean(false),當然

alert(NaN === NaN); // false 
var NAN = new Number(NaN); 
alert(NAN === NAN); // true 

===!==參照所有的StringNumberBoolean比較。

+0

除了布爾邏輯和'!'操作符。還有什麼其他的東西在盒裝VS原始類型上蠻橫作用。我們是否應該檢查/反對這個? – Raynos

+0

@Raynos,顯然'new Number(0)'是truthy和'var NAN = new Number(NaN);警報(NAN === NAN && !! NAN)'。 –

-2

我使用underscore.js方法來檢測變量的類型。嘗試使用: 的isEmpty,isElement,IsArray的,isArguments,isFunction,isString,ISNUMBER,isBoolean,而isDate,isRegExp isNaN,則isNull,isUndefined

說明如下: http://documentcloud.github.com/underscore/

+1

我們不是在談論類型,而是在談論檢查某個特定類型的值是原始類型還是盒裝類型(String,Number,Boolean) – Raynos

+0

對不起。我誤解了這個問題。 – czerasz

相關問題