2008-05-28

JavaScriptのプリミティブ型と参照型

ずっとマニアックなネタが続いたいたので今回は基本的なJavaScriptの型のお話。JavaScriptにはプリミティブ型と参照型があるのはご存知でしょうか。例えば次の二つの文字列は同じ"aiueo"という文字列ですが、プリミティブ型と参照型の違いがあります。
var p = "aiueo";   // プリミティブ型
var r = new String("aiueo"); // 参照型

通常、文字列を定義する場合はStringコンストラクタは使わずに直接記述すると思います。これはプリミティブ型でtypeof演算子で"string"と判別されます。またStringコンストラクタを使って定義すると参照型となり、typeof演算子で"object"と判別されます。
両者は同じようにプロパティへアクセスすることができ、普通に使う分には違いを感じないと思います。二つには違いはどこにあるのでしょうか。文字列を例に違いの一部を表にしてみました。

 プリミティブ型参照型
typeof演算子(typeof(x))"string""object"
instanceof演算子(x instanceof String)falsetrue
プロパティの定義不可
同じ値を===演算子で比較truefalse

基本的なところで大きく違うことがわかると思います。この中で余り知られていないのはプロパティの定義ではないでしょうか。次のコードを実行すると、文字列にくっつけたプロパティが参照型の値では取得できますが、プリミティブ型ではundefinedとなります。
var p = "aiueo";
var r = new String("aiueo");
p.id = 100;
r.id = 200;

alert(p); // undefined
alert(r); // 200
alert(p.hasOwnProperty("id")); // false
alert(r.hasOwnProperty("id")); // true

JavaScriptでコーディングする際はこの違いを意識して書くとミスも減ると思います。最後にプリミティブ型と参照型を区別なく判定する小技と一つ。型判定はtypeof演算子やinstanceof演算子を使うのではなく、constructorプロパティで行うとプリミティブ型と参照型を区別なく判定できます。例を下記します。
var p = "aiueo";
var r = new String("aiueo");
alert(p.constructor === String); // true
alert(r.constructor === String); // true

0 件のコメント: