2011-07-22 6 views
16

typeofを使用して、値がプリミティブであるかボックスであるかを判断できます。値がプリミティブであるかボックスであるかにかかわらず

は考えてみましょう:私たちは次の2つの関数

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"; 
}; 

を定義することができObject.prototype.toStringと組み合わせて

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

は、この2つの関数のための任意のユースケースがありていますか? (NumberBooleanなどの機能)。

この質問の背後にあるコンセプトは、次のとおりです。Comment by T.J.Crowder

私たちが持っている価値が原始的であるか、または箱に入れられているかどうかは今まで気にかかっていますか?

答えて

7

私はほとんどない点がありますでしょうねstringプリミティブかStringオブジェクトを扱っているかどうかはほとんど気にしません。

エッジケースがあります。たとえば、Stringオブジェクトは実際のオブジェクトです。プロパティを追加できます。これは、あなたがこのようなことを行うことができます:

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

呼び出すコードがプリミティブstringに合格した場合:

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

... argStringオブジェクトに昇格取得し、プロパティがそれに追加されますしかし、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

s1プリミティブ文字列、我々はそれを推進したときに作成されたオブジェクトだったので(s2.fooは文字列ですが、s1.fooではないことtestには呼び出しコードとは関係ありません)。

これにはどのような用途がありますか?ダニー。もしそうなら、非常にぎこちないエッジケースになると思います。

+0

ボックス化された値がプリミティブと比較して「参照渡し」されているという事実は、興味深い結果をもたらす可能性があります。 – Raynos

+1

@レイノス、どんな結果?プリミティブは不変であるため、プリミティブの値渡しと参照渡しの間には、目に見える差異がないはずです。私はあなたが書くことができるプログラムはありません。それは、すべての 'true'が単一のメモリ位置(Rhinoのような)にある不変オブジェクトへの参照として渡されるのか、それがタグ付きの共用体であるのかそれは他のほとんどの通訳のようにコピーされます。 –

3

すべてのtoStringは、さまざまな組み込みのコンストラクタのクロスフレームミキシングでの回避方法の問題を解決しようとしているようです。これは何かがプリミティブな文字列かどうかをチェックするためには不要です。typeofで十分であるので、is_primitive_stringのユースケースはありません。

私が何かではなく、単に("" + s)またはString(s)経由String値に強制変換のStringインスタンスクロスフレームであるかどうかを確認する必要があるだろう、なぜ私が見ることができないので、私は非常にまれ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 strictモードが"use strict";が有効なES5インタプリタにBoolean.prototype.notの先頭に追加されたときに1が単純に期待するかもしれないとして最後の例(false.not())が動作しますので、thisが提示された方法を変えていると信じています。

Numberを使用すると、<を使用した比較はOKであり、追加およびその他の演算子は期待どおりに動作する傾向があります。 new Number(0)new Number(NaN)条件周りnew Boolean(false)と同じ問題を抱えている、とStringNumber、及びBooleanの全てのために参照により比較もちろん

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

===!==

+0

ブール論理と '! '演算子の他に、ボックス型とプリミティブ型で奇妙に作用するものは他にありますか?そして、これに対して/ガードをチェックするべきですか? – Raynos

+0

@Raynos、明らかに 'new Number(0)'は真実で '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

関連する問題