TIL 76|JS Closure(2)使用と注意事項
なぜCloser(1)はCloserなのですか?
*利用情報公開
最初に出現したモジュールの概念から見ると、JavaScriptのすべての関数はモジュールである.なぜなら、関数を作成し、関数内部のコードナビゲーションのスキャンを関数作成時の語彙scopeに固定すると、モジュールになるからです.
しかし,実際にはすべてのJavaScript関数をCloserと呼ぶわけではない.
通常、外部アクセスを制限する専用変数が環境に存在する場合は、エンクロージャと呼ばれます.この場合、下一篇に記載のエンクロージャを使用する理由は正しい.
エンクロージャの用途の要約:情報の非表示とパッケージング
1.キャビネットで非表示
1-1. IIFEの使用
匿名関数はすぐに実行され、
匿名関数の戻り値である3つの関数は、同じ語彙環境を共有し、共通関数=特権メソッド=公開メンバー 非公開メンバー 1-2. 記名関数の使用
IIFEではなく記名関数を使用する場合、独立性を維持する複数のカウンタを生成することができる.
各モジュールは、異なるバージョンの
1つのモジュールで変数値を変更しても、他のモジュールの値には影響しません.
2.Curryingによるテンプレート化
Curryingは、複数のパラメータを受信する関数を、単一のパラメータを受信する関数チェーンを使用する方法に変換することを意味する.記名関数を使用すると、上記の例のcurryingを組み合わせて、Closer関数の外部関数をテンプレートとして使用できます.
パフォーマンスとメモリの問題エンクロージャは、メキシコ環境を記憶するためにメモリを消費します.GCは内部変数によって消費されるメモリを自動的に回収しないため、モジュールを使用した後、参照を削除し、JavaScriptがメモリを回収できることを通知し、メモリの浪費を避ける必要があります. scopeチェーンを遡る行為があるので、少し遅いです. 反復文モジュール
キャビネットの理解が不十分な場合は、文を繰り返してキャビネットと一緒に使用すると、予想とは異なる結果が得られます.下一篇で最初に提起された問題を再びもたらした.
実績出力結果:5、5、5、5、5
settimeoutだけでなく,イベントリスナーなどの繰り返し文ループ後に実行できるcloser関数にも注意する.コードを予想通りに動作させるには、次の方法で解決します.
ソリューションIIFE + parameter
n/a原理
settimeout関数の外に新しいscopeを作成し、IIFEで
独立した語彙環境を有し、各時点の
ソリューションES 6に追加されたBlock Scope
n/a原理
varには関数レベルがあり、letにはブロックレベルのスキャンがあります.
すなわちletキーワードを使用するブロックに対してlexicalenvironmentが再生成される.
繰り返し文は実行するたびにモジュールを生成するため、iは各時点のiにアクセスし、増加した数値を出力することができる.
JavaScriptモジュール(Close)
JavaScript/スキャン、クローズ、インスタント実行関数の学習(IIFE)
*利用情報公開
最初に出現したモジュールの概念から見ると、JavaScriptのすべての関数はモジュールである.なぜなら、関数を作成し、関数内部のコードナビゲーションのスキャンを関数作成時の語彙scopeに固定すると、モジュールになるからです.
しかし,実際にはすべてのJavaScript関数をCloserと呼ぶわけではない.
通常、外部アクセスを制限する専用変数が環境に存在する場合は、エンクロージャと呼ばれます.この場合、下一篇に記載のエンクロージャを使用する理由は正しい.
エンクロージャの用途の要約:情報の非表示とパッケージング
1.キャビネットで非表示
1-1. IIFEの使用
var counter = (function() {
var privateCounter = 0; ┐
function changeBy(val) { │ increment, decrement, value
privateCounter += val; │ 세 메소드가 공유하는 private items
} ┘
return {
increment: function() {
changeBy(1);
},
decrement: function() {
changeBy(-1);
},
value: function() {
return privateCounter;
}
};
})();
console.log(counter.value()); // logs 0
counter.increment();
counter.increment();
console.log(counter.value()); // logs 2
counter.decrement();
console.log(counter.value()); // logs 1
コードの説明匿名関数はすぐに実行され、
counter
変数に関数の戻り値が割り当てられます.匿名関数の戻り値である3つの関数は、同じ語彙環境を共有し、
privateCounter
およびchangeBy()
にアクセスできる唯一のモジュールである.counter.increment
counter.decrement
counter.value
privateCounter
changeBy
IIFEではなく記名関数を使用する場合、独立性を維持する複数のカウンタを生成することができる.
var makeCounter = function() {
var privateCounter = 0;
function changeBy(val) {
privateCounter += val;
}
return {
increment: function() {
changeBy(1);
},
decrement: function() {
changeBy(-1);
},
value: function() {
return privateCounter;
}
}
};
var counter1 = makeCounter();
var counter2 = makeCounter();
alert(counter1.value()); /* 0 */
counter1.increment();
counter1.increment();
alert(counter1.value()); /* 2 */
counter1.decrement();
alert(counter1.value()); /* 1 */ ┐ counter1과 counter2는
alert(counter2.value()); /* 0 */ ┘ 서로 다른 독립된 클로저를 가진다.
コードの説明各モジュールは、異なるバージョンの
privateCounter
変数(独自のモジュールを介して)を参照します.1つのモジュールで変数値を変更しても、他のモジュールの値には影響しません.
2.Curryingによるテンプレート化
Curryingは、複数のパラメータを受信する関数を、単一のパラメータを受信する関数チェーンを使用する方法に変換することを意味する.記名関数を使用すると、上記の例のcurryingを組み合わせて、Closer関数の外部関数をテンプレートとして使用できます.
function greetCurried (greeting) {
return function (name) {
console.log(greeting + ", " + name);
}
}
greetCurried("Hi there")("Howard"); //"Hi there, Howard"
let greetHello = greetCurried("Hello");
greetHello("Heidi"); //"Hello, Heidi"
greetHello("Eddie"); //"Hello, Eddie"
let greetGoodmorning = greetCurried("Good morning");
greetGoodmorning('wendy'); // Good morning, wendy
greetGoodmorning('honey'); // Good morning, honey
*使用上の注意パフォーマンスとメモリの問題
キャビネットの理解が不十分な場合は、文を繰り返してキャビネットと一緒に使用すると、予想とは異なる結果が得られます.下一篇で最初に提起された問題を再びもたらした.
function count() {
var i;
for (i = 0; i < 5; i++) {
console.log(i)
setTimeout(function() {
console.log(i)
}, i*1000)
}
}
count();
作者の意図💭 : 0、1、2、3、4は1秒間隔で出力されます!実績出力結果:5、5、5、5、5
settimeoutだけでなく,イベントリスナーなどの繰り返し文ループ後に実行できるcloser関数にも注意する.コードを予想通りに動作させるには、次の方法で解決します.
ソリューションIIFE + parameter
n/a原理
settimeout関数の外に新しいscopeを作成し、IIFEで
i
をパラメータとして渡します.i
を増加させるごとに、固定されたcountingNumber
とは独立したCloser関数が生成される.独立した語彙環境を有し、各時点の
countingNumber
にアクセスして出力することができる. function count() {
var i;
for (i = 0; i < 5; i++) {
(function(countingNumber) {
setTimeout(function() {
console.log(countingNumber)
}, i*1000)
})(i);
}
}
count(); //0,1,2,3,4
(+)settimeoutでなければ、新しいスキャンを作成せず、IIFEを適用するだけで問題を解決できます.ただし、settimeoutは、コールバック伝達の関数自体にIIFEを適用すると、2番目のパラメータとしての遅延は機能しないため、外部に新しいスキャンを作成して適用するしかありません.ソリューションES 6に追加されたBlock Scope
n/a原理
varには関数レベルがあり、letにはブロックレベルのスキャンがあります.
すなわちletキーワードを使用するブロックに対してlexicalenvironmentが再生成される.
繰り返し文は実行するたびにモジュールを生成するため、iは各時点のiにアクセスし、増加した数値を出力することができる.
function count() {
'use strict';
for (let i = 0; i < 5; i++) {
setTimeout(function timer() {
console.log(i);
}, i*1000);
}
}
count(); //0,1,2,3,4
参考資料JavaScriptモジュール(Close)
JavaScript/スキャン、クローズ、インスタント実行関数の学習(IIFE)
Reference
この問題について(TIL 76|JS Closure(2)使用と注意事項), 我々は、より多くの情報をここで見つけました https://velog.io/@mygomi/TIL-76-JS-Closure2-활용과-주의사항テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol