on
Core JavaScript 1.データタイプ - undefinedとnull
この記事はweb開発に欠かせないJavaScriptのコアな概念をしっかり理解しようということでCore Javascript(韓国語)を要約した内容になります。
undefinedとnull
undefinedとnullはどちらも「何もない」状態を示す値である。
undefinedはJavaScriptエンジンが勝手に付与する場合がある。
undefinedを付与する場合
var a;
console.log(a); // (1) undefined. 値を代入していない変数のため
var obj = { a: 1 };
console.log(obj.a); // 1
console.log(obj.b); // (2) undefined. 存在しないプロパーティのため
console.log(b); // ReferenceError: b is not defined
var func = function() {};
var c = func();
console.log(c); // (3) undefined. returnがないと、undefinedが返却されたことになる
(1)の何も代入していない場合、配列だとまた異なる振る舞いをする。
undefinedと配列
var arr1 = [];
arr1.length = 3;
console.log(arr1); // [empty x 3]
var arr2 = new Array(3);
console.log(arr2); // [empty x 3]
var arr3 = [undefined, undefined, undefined];
console.log(arr3); // [undefined, undefined, undefined]
arr1
とarr2
は[empty x 3]
が出力される。配列に3つの要素を確保するだけでは各要素にはnullもundefinedも割り当てられていない。
リテラルで宣言したarr3
は、配列を生成する共にundefinedを各要素に付与したので、同然ながらundefinedと出力される。
undefined
を割り当てた要素と違って空いている要素
はループ関連メソッドの巡回対象から除外される。
空いている要素と配列の巡回
var arr1 = [undefined, 1];
var arr2 = [];
arr2[1] = 1;
console.log(arr2[0]) //undefined
console.log(arr2[99]) //undefined
arr1.forEach(function (v, i) { console.log(v, i); }); //undefined 0 / 1 1
arr2.forEach(function (v, i) { console.log(v, i); }); // 1 1
arr1.map(function (v, i) { return v + i; }); //[NaN, 2]
arr2.map(function (v, i) { return v + i; }); //[empty, 2]
arr1はundefined
と1
を直接割り当てていて、arr2はインデックス1に1
を割り当てている。
arr1は配列の全ての要素を取り出して結果を出力するが、arr2は空いている要素を飛ばしてしまい、インデックス1の要素だけだ出力される。
配列は必ず指定したlength分メモリ空間を確保すると思われがちだが、 オブジェクトのプリパーティと同じく、特定のインデックスに値を割り当てることでデータのアドレスを保存する等の動作をする。
undefinedは「何もない」ことを示す値なので、そのアドレスが要素の変数領域に保存されるので、繰り返しメソッドの巡回対象になる。 なのでメモリ上に存在するデータだが、JavaScriptエンジンが返すundefinedは値ないないことを示すだけだ。
undefinedにはこのようなクセがあるため、直接undefinedを割り当てるのは避けるべきだ。 JavaScriptユーザーは明視的に「ない」を値として使いたい場合はnullを使えば良い。 そうすることで、undefinedはJavaScrptエンジンが返却する値として扱うことができる。
nullとundefinedの比較
等値演算子(==
)で比較すると同じ値だと判定してtrueが返る。
同値演算子(===
)で比較するとタイプまで厳密に比較するのでfalseが返る。
var n = null;
console.log(n == undefined); //true
console.log(n === undefined); //false