kidoOooOoooOOom

IT系で開発やってます

Effective JavaSceipt 読書メモ 項目8~11

第2章 変数のスコープ

項目8 グローバルオブジェクトを使うのは、最小限にとどめる

JSではグローバル名前空間に変数を作る事はあまりにも簡単。変数定義時に何も宣言する必要がない。
経験を積んだプログラマほど、グローバル空間の汚染はバグを産み、コードを追いにくくすることは分かっている。
できるだけ変数はそれを必要とするコードだけがアクセスできるローカル変数にすべきである。

項目9 ローカル変数は、かならず宣言しよう

グローバル変数よりも厄介なものは、偶発的なグローバル変数である。
var をつけずに宣言してしまった変数は、容赦なくグローバル変数になってしまう。
これを避けるためにも、変数をチェックできる lintツールの導入は必須。

項目10 withは避けよう

(withは使ったことないけれど)悪質な機能とのこと。
withはとにかく使うなという結論である。

項目11 クロージャと仲良くしよう

クロージャを理解するには、3つの基本的な事実を学ぶだけでよい。

第1の事実:JSでは現在の関数の外側で定義された変数を参照できる。

function makeSandwich() {
  var hoge = "hoge";
  function make(filling) {
    return hoge + " and " + filling; // 関数の外側で定義された hoge 変数を参照できる
  }
  return make("foo");
}
makeSandwich();

第2の事実: 関数は、その外側の関数がリターンした後になっても、まだ外側の関数内で定義された変数を参照できる。

function makeSandwich() {
  var hoge = "hoge";
  function make(filling) {
    return hoge + " and " + filling; // 関数の外側で定義された hoge 変数を参照できる
  }
  return make;
}
var f = makeSandwich();
f('test'); // hoge and test
f('banana'); // hoge and banana

このカラクリとしては、JSの関数値は呼び出されたときに必要となる情報を含むが、それは実行すべきコードだけではない。その関数を囲むスコープの中で定義されている変数を参照する可能性があれば、それらの変数も内部的に保存する。このように、自分を囲むスコープにある変数を覚えている関数を、クロージャと呼ぶ。

第3の事実: クロージャは外側の変数を更新できる。クロージャは、外側の変数へのリファレンスを保存するのであって、値をコピーするわけではない。したがって、変数の更新は、それをアクセスするすべてのクロージャに反映される

function box() {
  var val = undefined;
  return {
    set: function(newVal) { val = newVal; },
    get: function() { return val; },
    type:  function() { return typeof val; }
  }
}

var b = box();
console.log(b.type()); // undefined
b.set(98.6);
console.log(b.get()); // 98.6
console.log(b.type()); // number