ホームページ >ウェブフロントエンド >jsチュートリアル >JavaScript クロージャーの簡単な紹介
この記事では、JavaScript に関する関連知識を提供します。主に JavaScript クロージャに関連する問題を紹介します。クロージャの概念には多くのバージョンがあり、クロージャについては場所によって意見が異なります。以下は、見てみましょう。みんなを助けます。
#クロージャとは何ですか? クロージャの概念には多くのバージョンがあり、さまざまな場所でクロージャについてさまざまな意見がありますWikipedia: コンピュータ サイエンスでは、クロージャ (英語: Closure)、レキシカル クロージャまたはレキシカル クロージャとも呼ばれます。関数クロージャとは、ファーストクラス関数をサポートするプログラミング言語で字句バインディングを実装するための手法です。
MDN:closure (クロージャ) は、関数とそのバンドルされた周囲の環境状態 (字句環境、字句環境 ##) です。 #) は参照の組み合わせです。 #個人的な理解:
Closure は関数 (関数を返す)
function fn() { let num = 1; return function (n) { return n + num } }let rFn = fn()let newN = rFn(3) // 4num 変数のスコープは fn 関数内にありますが、rFn 関数は num 変数にアクセスできます。これは、クロージャー関数が外部関数変数にアクセスできることを意味します。 ブラウザのデバッグと VSCode Nodejs のデバッグからクロージャを確認する
VS Code は連携しますNode.js
を使用して、Closure の fn が num 変数を保存するクロージャー関数であることを確認します。
古典的なクロージャ: シングルスレッドのイベント メカニズムのループ問題と解決策for (var i = 1; i { console.log(i); }, i * 1000); }出力結果はすべて 6 ですが、なぜですか?
for ループは同期タスクです
for (var i = 1; i { console.log(i); }, i * 1000); }解決策 2: 自己実行関数クロージャー
for (var i = 1; i { console.log(i); }, i * 1000) })(i) }
add 関数のfor (var i = 1; i { console.log(j); }, 1000 * i, i); }クロージャと関数curry
function add(num) { return function (y) { return num + y; }; };let incOneFn = add(1); let n = incOneFn(1); // 2let decOneFn = add(-1); let m = decOneFn(1); // 0
実際の効果
使用シナリオ
time を受け入れます。これらはすべて、
function throttle(fn, time=300){ var t = null; return function(){ if(t) return; t = setTimeout(() => { fn.call(this); t = null; }, time); } }
アンチシェイク関数function debounce(fn,wait){ var timer = null; return function(){ if(timer !== null){ clearTimeout(timer); } timer = setTimeout(fn,wait); } }##は、単純なsetTimeoutバージョンです。 #React.useCallback クロージャー トラップの問題
問題の説明:
親/子 を通じて最適化されます。つまり、この最適化された関数にはクロージャ トラップがあります (初期状態値は常に保存されます) <pre class="brush:php;toolbar:false">import { useState, useCallback, memo } from "react";const ChildWithMemo = memo((props: any) => { return ( <div>
<button>Child click</button>
</div>
);
});const Parent = () => { const [count, setCount] = useState(1); const handleClickWithUseCallback = useCallback(() => { console.log(count);
}, []); // 注意这里是不能监听 count, 因为每次变化都会重新绑定,造成造成子组件重新渲染
return ( <div>
<div>parent count : {count}</div>
<button> setCount(count + 1)}>click</button>
<childwithmemo></childwithmemo>
</div>
);
};export default Parent</pre>
ChildWithMemo は最適化にメモを使用し、
解決策は、 useRef を使用して操作変数関数を保存することです:import { useState, useCallback, memo, useRef } from "react";const ChildWithMemo = memo((props: any) => { console.log("rendered children") return ( <div> <button> props.countRef.current()}>Child click</button> </div> ); });const Parent = () => { const [count, setCount] = useState(1); const countRef = useRef<any>(null) countRef.current = () => { console.log(count); } return ( <div> <div>parent count : {count}</div> <button> setCount(count + 1)}>click</button> <childwithmemo></childwithmemo> </div> ); };export default Parent</any>この問題に対応して、React は useEvent を追加するというコミュニティの提案を一度承認しましたが、その後 useEvent セマンティクスがレンダリングの最適化のために、React はコンパイル最適化ソリューションを採用しています。実はuseEffectでも同様の問題が発生しますので、使用する際はクロージャトラップに注意してください。
[関連する推奨事項:
- 開発者ツールを開き、タイムライン パネルを選択します
- をチェックし、左上隅の記録ボタンをクリックします。
Capture#フィールドの一番上の ## メモリ
- ページ上でさまざまな操作を実行して、ユーザーの使用状況をシミュレートします。
- 一定の時間が経過した後、ダイアログ ボックスの停止ボタンをクリックすると、この期間のメモリ使用量がパネルに表示されます。
JavaScript ビデオ チュートリアル 、Web フロントエンド ]
以上がJavaScript クロージャーの簡単な紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。