[Effective JavaScript]クロージャ
更新日:2019.04.27
作成日:2016.01.30
いい加減、JavaScriptも使えるようになっておきたいので、お勉強。やっぱりよく分からないクロージャについて。
項目11 クロージャと仲良くしよう
ポイント1 JavaScriptでは現在の関数の外側で定義された関数を参照できる
内側のmake
関数はmagicIngredient
を参照しているが、これは外側のmakeSandwich
関数の中で定義されているもの。
function makeSandwich() {
var magicIngredient = "peanut butter";
function make(filling) {
return magicIngredient + " and " + filling;
}
return make("jelly");;
}
console.log(makeSandwich());
console.log(makeSandwich());
これがクロージャーだーって言って身構えてパッと見るとよくわからないが、処理を追っていけば、
ポイント2 関数は、その外側の関数がリターンした後になっても、まだ外側の関数内で定義された変数を参照できる
- 関数は、次のように、後で呼び出された時、内側の関数を返す形式で書くことができる
function sandwichMaker() {
var magicIngredient = "peanut butter";
function make(filling) {
return magicIngredient + " and " + filling;
}
return make;
}
var f = sandwichMaker();
console.log(f("jelly"));
JavaScriptの関数値は、呼び出された時に必要となる情報を含む。 その関数を囲むスコープの中で定義されている変数を参照する可能性があれば、それらの変数も内部的に保存する。
このmake関数は、自分のコードでmagicIngredientとfillingという、2つの外側の変数を参照するクロージャーである。
以下の関数式には名前がない(anonymous)。名前をつける必要がないのはこの関数を、新しい関数値を生成するために評価するためだけに使っており、直接呼び出すつもりがないためである。
function sandwichMake(magicIngredient) {
function make(filling) {
return magicIngredient + " and " + filling;
};
return make;
}
var hamAnd = sandwichMake("ham");
console.log(hamAnd("cheese")); //ham and cheese
console.log(hamAnd("mustard")); //ham and cheese
var tukeyAnd = sandwichMake("turkey");
console.log(tukeyAnd("Swiss")); //turkey and Swiss
console.log(tukeyAnd("Provolone")); //turkey and Provolone
ポイント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()); // undefinded
b.set(98.6);
console.log(b.get()); // 98.6
console.log(b.type()); // number
これも、そういうもんなんだと思えば、身構える必要もないのかと。実際の利用例をもっと見てみたい。
ポイント
- 関数は、その外側のスコープで定義された変数を参照できる
- クロージャは、自分を作成した関数よりも長生きすることができる
- クロージャは内部で、外側の変数へのリファレンスを保存する。その変数は、読むことも更新することもできる
Related contents
TECH
2016.09.03
Hubotで外部コマンドを実行する
TECH
2016.08.28
AceエディタをElectronに組み込む
TECH
2016.08.27
javascript this bind
TECH
2016.08.24
React + ElectronでFlickr連携可能なMarkdown Editorを作った
TECH
2016.05.11
Electronがv1.0.0になったのでMithril.jsと合わせてAmazonアフィリエイトリンクビルダーを作った
TECH
2016.02.20
ElectronでAmazonアフィリエイトリンクビルダーを作った
TECH
2016.02.07
D3.jsで東京の地価データを可視化する
TECH
2016.02.07
JavaScript Ninjaの極意 「関数の呼び出し」