エンクロージャ|コアJavaScript 5
17188 ワード
モジュールの意味と原理を理解する
特長
例
outerの実行コンテキストが終了すると、内部関数を呼び出すことはできません.
上のコードはinner関数の結果値のみouther 2に格納します.
outerの実行コンテキストが終了しても、宣言された内部関数にアクセスできます.
またouter変数も使用できます.
内部関数の実行コンテキスト
環境レコード:収集する情報がありません(宣言された変数はありません)
外部環境参照:内部関数宣言位置のLexicalEnvironmentが参照にコピーされます->外部関数の辞書環境が保存されます.
カーネル実行時(
let outer2=outer()
)、outer関数は実行を停止しました->どのようにアクセスしますか?==ゴミ収集器の挙動により
変数が値を参照している場合、ゴミ収集器はその値を収集ターゲットに含めません.
LexicalEnvironmentが関数の実行コンテキストの終了後もゴミ収集器の収集ターゲットから除外されている場合、参照領域変数の内部関数は唯一の外部伝達である.
規格により、宣言時のLexicalEnvironmentは全てGCすることはないが、2019規格はChromeまたはNodeである.jsなどで使用されているv 8エンジンについては,内部関数で実際に使用されている変数のみを保持し,残りの最適化はGCとする.
そのため、いわゆるシャーシです.
エンクロージャとメモリ管理
実行コンテキストが終了しても、モジュールには変数が存在します.
->ストレージ容量の継続的な使用
需要が消えた後にメモリを消費しないように、識別子に非参照型の基本型データ(null/undefined)を割り当て、参照カウントを0にすることが望ましい.
エンクロージャのメモリ解放例
return
let outer = (function() {
let a = 1;
let inner = function() {
return ++a;
}
return inner;
})();
console.log(outer());
console.log(outer());
//outer 식별자의 inner함수 참조를 끊음.
outer = null
setInterval
eventListener
(function() {
let count = 0;
let button = document.createElement('button');
button.innerText = 'click'
let clickHandler = function() {
console.log(++count, 'time clicked');
if(count >= 10) {
button.removeEventListener('click', clickHandler);
// clickHandler 식별자의 함수 참조를 끊음
clickHandler = null;
}
}
button.addEventListener('click', clickHandler);
document.body.appendChild(button)
})
エンクロージャ使用例
コールバック関数で外部データを使用する場合
1
let fruits = ['banana', 'apple', 'lemon'];
let $ul = document.createElement('ul');
fruits.forEach(function(fruit){
let $li = document.createElement('li');
$li.innerText = fruit;
$li.addEventListener('click', function() {
alert('this is '+fruit)
})
$ul.appendChild($li)
});
document.body.appendChild($ul)
2
let fruits = ['banana', 'apple', 'lemon'];
let $ul = document.createElement('ul');
let alertFruit = function(fruit){
alert('this is ' + fruit)
}
fruits.forEach(function(fruit){
let $li = document.createElement('li');
$li.innerText = fruit;
$li.addEventListener('click', alertFruit.bind(null, fruit));
$ul.appendChild($li)
})
document.body.appendChild($ul)
addEventListenerはコールバック関数を呼び出すときに「イベントオブジェクト」を最初のパラメータに注入するためbindメソッドを使用してこの問題を解決します.
しかし、この場合、次のような問題が発生します.
let outer = (function() {
let a = 1;
let inner = function() {
return ++a;
}
return inner;
})();
console.log(outer());
console.log(outer());
//outer 식별자의 inner함수 참조를 끊음.
outer = null
(function() {
let count = 0;
let button = document.createElement('button');
button.innerText = 'click'
let clickHandler = function() {
console.log(++count, 'time clicked');
if(count >= 10) {
button.removeEventListener('click', clickHandler);
// clickHandler 식별자의 함수 참조를 끊음
clickHandler = null;
}
}
button.addEventListener('click', clickHandler);
document.body.appendChild(button)
})
コールバック関数で外部データを使用する場合
1
let fruits = ['banana', 'apple', 'lemon'];
let $ul = document.createElement('ul');
fruits.forEach(function(fruit){
let $li = document.createElement('li');
$li.innerText = fruit;
$li.addEventListener('click', function() {
alert('this is '+fruit)
})
$ul.appendChild($li)
});
document.body.appendChild($ul)
2
let fruits = ['banana', 'apple', 'lemon'];
let $ul = document.createElement('ul');
let alertFruit = function(fruit){
alert('this is ' + fruit)
}
fruits.forEach(function(fruit){
let $li = document.createElement('li');
$li.innerText = fruit;
$li.addEventListener('click', alertFruit.bind(null, fruit));
$ul.appendChild($li)
})
document.body.appendChild($ul)
addEventListenerはコールバック関数を呼び出すときに「イベントオブジェクト」を最初のパラメータに注入するためbindメソッドを使用してこの問題を解決します.しかし、この場合、次のような問題が発生します.
3
let fruits = ['banana', 'apple', 'lemon'];
let $ul = document.createElement('ul');
let alertFruit = function(fruit){
return function () {
alert('this is ' + fruit)
}
}
fruits.forEach(function(fruit){
let $li = document.createElement('li');
$li.innerText = fruit;
$li.addEventListener('click', alertFruit(fruit));
$ul.appendChild($li)
})
document.body.appendChild($ul)
アクセス権制御(情報の非表示)
モジュール内部の論理の外部曝露を最小限に抑え、モジュール間の結合を低減し柔軟性を向上させることを目的とする概念.
outer関数から返される情報に外部からのみアクセスできます.return変数はpublicに変わります.そうしないとprivateになります.
ローカル適用関数
関数モジュールをコアテクノロジーとして使用すると、n個のパラメータを受け入れる関数にm個のパラメータを予め記憶してから、(n−m)個のパラメータを後でスキップして、元の関数の実行結果を得ることができます.
部分関数を使用する最適な例-ジッタ
同じイベントが短時間で大量に発生した場合、最初のイベントまたは最後のイベントのみが処理され、すべてのイベントは処理されません.
スクロール、ローラー、mousemove、resizeなどのツールを使用してフロントエンドのパフォーマンスを最適化
コリンかんすう
複数のパラメータを受信する関数を1つのパラメータのみを受信する関数に分けてチェーン形式で順次呼び出す.
必要な情報のみが受信され、必要な情報が受信されたときに転送される場合、関数の実行は、最後のパラメータの前=
지연 실행
に遅延される.ローカル適用関数との違い
1回に1つのパラメータ
Reference
この問題について(エンクロージャ|コアJavaScript 5), 我々は、より多くの情報をここで見つけました https://velog.io/@deli-ght/클로저-코어자바스크립트-5テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol