前面に書かれています
JavaScript ほとんど神話 JavaScript の使用経験はあるものの、クロージャの概念を実際には理解したことがない人にとって、クロージャを理解することは、ある種の生まれ変わりとなります。クロージャは、使用するために新しい構文を学習する必要があるツールではありません。クロージャは、字句スコープに基づいてコードを作成した場合の自然な結果です。言い換えれば、クロージャのためにクロージャを作成する必要はなく、作成するコードのどこにでもクロージャが存在します。 クロージャを本当に理解すると、ああ~、前に入力したコードにはたくさんのクロージャがあったことがわかります。
小さなデモ
次の例を注意深く見てみると、奇妙に感じるでしょう。これらはすべて result() を呼び出しているのに、なぜ結果が違う?
let count=500 //全局作用域 function foo1() { let count = 0;//函数全局作用域 function foo2() { count++;//函数内部作用域 console.log(count); return count; } return foo2;//返回函数 } let result = foo1(); result();//结果为1 result();//结果为2
まず第一に、foo1() は foo2() 関数を返します。result() を呼び出すと、foo2() によって実行された関数が返されます。foo2() には何が含まれていますか? まず次のようになります。以下のように count 変数がありますが定義されていません JavaScript のスコープチェーンの定義により、関数内の変数が定義されていない場合はバブリング方式で上位を検索します次のレベルには続行しません。最上位ウィンドウまで 1 レベルを検索します。何もない場合は、未定義のエラーが報告されます。ここでは、foo1() で count を見つけるので、count 1、最初の出力は 1、そこにあります問題ありません。
function foo2() { count++; console.log(count); return count; }
しかし、2 回目に result() を実行したときに問題が発生しました。なぜ 2 なのでしょうか? 処理によると、まず foo2() 関数内の count を探します。カウントがない場合は、外側の層でそれを探します。カウント = 0 が見つかった場合、カウント 1 は 1 である必要があります。これには、クロージャーの問題が含まれます。
最初デバッガを追加し、Google Chrome を右クリックしてリソースをクリックすると、右側にクロージャが表示されます。ブラウザの視覚化により、これが実際にクロージャであることが確認されました。そして、count=1 がクロージャに保存されています。これは、count を意味します=1 は破棄されておらず、次回 result() が呼び出されるときに count=2 になります。
スコープの理解
Clussure を学ぶには、これを理解する必要があります。 JavaScript のスコープ関連の知識:
1. グローバル スコープ
2. 関数スコープ
4. ブロックレベル スコープ (es6 の新機能、var 問題を解決し、 let 、 const を追加)
var count = 100; //全局作用域 function foo1() { var count = 0; //函数全局作用域 return count; //返回函数 } if (count == 1) { //块级作用域 console.log(count); }
上記のコードは、スコープの分類を簡単に示しています。関数 (関数) もブロックレベルのスコープであることに注意してください。簡単に言うと、一般に {} をブロックとみなすことができます。レベル スコープ.
スコープ チェーン
スコープはスコープ内でネストされ、スコープ チェーンを形成します。外部スコープは内部スコープ スコープにアクセスできません。次の例を参照してください
function foo(){ var n=1 function foo2(){ var m=1 console.log(n) //1 } foo2() } foo() console.log(n) //err: n is not defined
上記のコードでは、内部 n にはグローバルにアクセスできませんが、ネストされた内部 foo2() は外部関数にアクセスできます。これは、スコープによって生成される特別な効果です。
さて、スコープ チェーンについては理解しました。例を見てみましょう (非常にわかりにくいので、注意して見てください):
var name = 'Mike'; //第一次定义name function showName() { console.log(name); //输出 Mike 还是 Jay ? } function changeName() { var name = 'Jay'; //重新定义name showName(); //调用showName() } changeName();
上記の例の出力は何だと思いますか? 答えはマイクです。ここで新しい概念を紹介します。字句スコープには 2 つのモデルがあります:
字句スコープ (静的): js 検索は、呼び出し時の位置ではなく、コードが記述されたときの位置に従って決定されます
動的スコープ: Perl と Bash が現在使用されています (これについては自分で学習できます)
私たち字句スコープのルールを通じて再度分析できます。
changeName() を呼び出すときは、この関数を見つけます
var name = "Jay" を定義します
showName()を呼び出します
changeName()にshowName()があるか確認します。このメソッドは見つからなかったので、外側のメソッドを検索しました。レイヤーを検索し、
を見つけました。console.log(name) を呼び出し、関数内を検索して名前があるかどうかを確認します。名前がない場合は、外側に検索して見つけました。name="Mike 「
アウトプットマイク
クロージャ
理解しました 上記の知識を経て、私はついにクロージャに到達しました
クロージャの公式説明は 2 冊の本で説明されています:
##1. 小さな「黄色の」本 (JavaScript を知らない人): クロージャは次の場合に生成されます。関数は、現在の字句スコープ外で実行された場合でも、その関数が含まれている字句スコープを記憶してアクセスできます。は非常に抽象的な概念です。私自身の理解の 1 つは次のとおりです。2. Little Red Book (JavaScript Advanced Programming) : クロージャとは、別の字句スコープにアクセスできることを意味します。 関数スコープ内の変数の関数
変数 (上記の名前など) が関数に対してローカルではない場合、変数は関数のパラメータではありません。スコープと比較すると、これは自由変数 (外部変数を参照) であり、クロージャを形成します。
何と言うか? 最初に使用するものを見てみましょうデモ###
let count = 500; //全局作用域 function foo1() { let count = 0; //函数全局作用域 function foo2() { let count2 = 1; //随便新增一个变量 // count++; 注释 debugger; //console.log(count); 注释 //return count; 注释 } return foo2; //返回函数 } let result = foo1(); result(); //结果为1 result(); //结果为2
再次使用浏览器看看,这时我们就发现Closure已经消失了,这也就证实我说的,如果函数内部不调用外部的变量,就不会形成闭包.但是如果调用了外部变量,那么就会形成闭包. 这也就是说不是所有的函数嵌套函数都能形成闭包
<img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/image/731/425/784/1592270826700856.jpg?x-oss-process=image/resize,p_40" class="lazy" title="1592270826700856.jpg" alt="JavaScriptのクロージャ内のクロージャ">
最后我们再来看一个循环闭包的例子
for (var i = 1; i <= 5; i++) { setTimeout(function timer() { debugger; console.log(i); // 输出什么? }, 1000); }
答案 6 6 6 6 6 .因为setTimeout里面的回调函数是一个异步的过程(异步代表可以不用等待我这个代码先执行完,可以先往后执行),而for循环是同步的(代码只能从上往下的执行),立即执行,异步的setTimeout必须等待一秒才能执行,这时i早已经循环结束了.
解决办法有三个:
将for循环中的var 改成let
for (let i = 1; i <= 5; i++) { setTimeout(function timer() { debugger; console.log(i); // 1 2 3 4 5 }, 1000); }
这样就没有问题了, 因为let是有块级的功能,每一层循环都是独立的,互不影响,所以才能正常输出.
2. 把setTimeout()套上一个function
for (var i = 1; i <= 5; i++) { log(i); // 1 2 3 4 5 } function log(i) { setTimeout(function timer() { debugger; console.log(i); }, 1000); }
这样同样能够实现这个功能,原理和第一个方法一样,每一个log()都是独立的,互不影响,这样才能有正确的结果,var就是因为没有块级的功能,才会出问题 3. 包装成匿名函数
for (var i = 1; i <= 5; i++) { (function (i) { setTimeout(function timer() { debugger; console.log(i); }, 1000); })(i) }
前面一个(func..)
定义函数,后面一个(i)调用,这再JavaScript叫做立即执行函数,其实与第二种方式是一样的,只是写法不一样.
结语
理解JavaScript闭包是一项重要的技能,在面试中也常常会有,这是迈进高级JavaScript工程师的必经之路.
推荐教程: 《js教程》
以上がJavaScriptのクロージャ内のクロージャの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

さまざまなJavaScriptエンジンは、各エンジンの実装原則と最適化戦略が異なるため、JavaScriptコードを解析および実行するときに異なる効果をもたらします。 1。語彙分析:ソースコードを語彙ユニットに変換します。 2。文法分析:抽象的な構文ツリーを生成します。 3。最適化とコンパイル:JITコンパイラを介してマシンコードを生成します。 4。実行:マシンコードを実行します。 V8エンジンはインスタントコンピレーションと非表示クラスを通じて最適化され、Spidermonkeyはタイプ推論システムを使用して、同じコードで異なるパフォーマンスパフォーマンスをもたらします。

現実世界におけるJavaScriptのアプリケーションには、サーバー側のプログラミング、モバイルアプリケーション開発、モノのインターネット制御が含まれます。 2。モバイルアプリケーションの開発は、ReactNativeを通じて実行され、クロスプラットフォームの展開をサポートします。 3.ハードウェアの相互作用に適したJohnny-Fiveライブラリを介したIoTデバイス制御に使用されます。

私はあなたの日常的な技術ツールを使用して機能的なマルチテナントSaaSアプリケーション(EDTECHアプリ)を作成しましたが、あなたは同じことをすることができます。 まず、マルチテナントSaaSアプリケーションとは何ですか? マルチテナントSaaSアプリケーションを使用すると、Singの複数の顧客にサービスを提供できます

この記事では、許可によって保護されたバックエンドとのフロントエンド統合を示し、next.jsを使用して機能的なedtech SaaSアプリケーションを構築します。 FrontEndはユーザーのアクセス許可を取得してUIの可視性を制御し、APIリクエストがロールベースに付着することを保証します

JavaScriptは、現代のWeb開発のコア言語であり、その多様性と柔軟性に広く使用されています。 1)フロントエンド開発:DOM操作と最新のフレームワーク(React、Vue.JS、Angularなど)を通じて、動的なWebページとシングルページアプリケーションを構築します。 2)サーバー側の開発:node.jsは、非ブロッキングI/Oモデルを使用して、高い並行性とリアルタイムアプリケーションを処理します。 3)モバイルおよびデスクトップアプリケーション開発:クロスプラットフォーム開発は、反応および電子を通じて実現され、開発効率を向上させます。

JavaScriptの最新トレンドには、TypeScriptの台頭、最新のフレームワークとライブラリの人気、WebAssemblyの適用が含まれます。将来の見通しは、より強力なタイプシステム、サーバー側のJavaScriptの開発、人工知能と機械学習の拡大、およびIoTおよびEDGEコンピューティングの可能性をカバーしています。

JavaScriptは現代のWeb開発の基礎であり、その主な機能には、イベント駆動型のプログラミング、動的コンテンツ生成、非同期プログラミングが含まれます。 1)イベント駆動型プログラミングにより、Webページはユーザー操作に応じて動的に変更できます。 2)動的コンテンツ生成により、条件に応じてページコンテンツを調整できます。 3)非同期プログラミングにより、ユーザーインターフェイスがブロックされないようにします。 JavaScriptは、Webインタラクション、シングルページアプリケーション、サーバー側の開発で広く使用されており、ユーザーエクスペリエンスとクロスプラットフォーム開発の柔軟性を大幅に改善しています。

Pythonはデータサイエンスや機械学習により適していますが、JavaScriptはフロントエンドとフルスタックの開発により適しています。 1. Pythonは、簡潔な構文とリッチライブラリエコシステムで知られており、データ分析とWeb開発に適しています。 2。JavaScriptは、フロントエンド開発の中核です。 node.jsはサーバー側のプログラミングをサポートしており、フルスタック開発に適しています。


ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

Safe Exam Browser
Safe Exam Browser は、オンライン試験を安全に受験するための安全なブラウザ環境です。このソフトウェアは、あらゆるコンピュータを安全なワークステーションに変えます。あらゆるユーティリティへのアクセスを制御し、学生が無許可のリソースを使用するのを防ぎます。

MantisBT
Mantis は、製品の欠陥追跡を支援するために設計された、導入が簡単な Web ベースの欠陥追跡ツールです。 PHP、MySQL、Web サーバーが必要です。デモおよびホスティング サービスをチェックしてください。

SAP NetWeaver Server Adapter for Eclipse
Eclipse を SAP NetWeaver アプリケーション サーバーと統合します。

SublimeText3 英語版
推奨: Win バージョン、コードプロンプトをサポート!

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)
