ホームページ > ウェブフロントエンド > jsチュートリアル > jsクロージャのコード例解説

jsクロージャのコード例解説

不言
リリース: 2018-10-26 15:48:58
転載
2524 人が閲覧しました

この記事の内容は、js クロージャのコード例を説明するものです。必要な方は参考にしていただければ幸いです。

正確には、クロージャは通常のガベージ コレクション処理メカニズムに基づいています。言い換えれば、一般に、関数 (関数スコープ) が実行された後、その中で宣言されたすべての変数はガベージ コレクターによって解放され、リサイクルされます。ただし、クロージャーは、関数の実行後にスコープ内の変数を保存し、ガベージ コレクションを行わないようにするトリックを使用します。

クロージャ

定義

MDN定義

javascriptkit

字句スコープ

スコープチェーン

関数の実行中、最初にできることは自分自身の中から変数を見つけるのではなく、現在の関数が作成されるスコープ (字句スコープ) から変数を探す必要があります。

スコープ チェーン ブログ

関数は、そのスコープ チェーン内で探している変数とともにクロージャを形成します

一般に、クロージャは主にデータをカプセル化するために使用されます

一時データ

典型的なクロージャのケース

function car(){
 var speed = 0
 function fn(){
 speed++
 console.log(speed)
 }
 return fn
}
var speedUp = car()
speedUp() //1
speedUp() //2
ログイン後にコピー

次のコードが関数内で実行されない場合

function fn(){
 speed++
 console.log(speed)
 }
return fn
ログイン後にコピー

コードの実行が完了した後、内部で関数 ローカル変数 SpeedUp は常に存在するため (現在のページが閉じられない限り、グローバル変数は常に存在します)、関数内のスコープは破棄できません。これは、ブラウザのガベージ コレクション メカニズムと同様です。speedUp() を実行すると、関数の字句スコープ内で検索が行われ、関数内で fn が返されるため、クロージャを形成できます。単純に

var speed = 0
function fn(){
 speed++
 console.log(speed)
}
ログイン後にコピー

として理解されます。このコード部分はクロージャを形成します。fn が返されない場合、関数内のローカル変数は破棄されます。

即時実行ステートメントと即時実行関数を使用して、上記のコードがどのように進化するかを見てみましょう:

function car(){
 var speed = 0
 function fn(){
 speed++
 console.log(speed)
 }
 return fn
}
var speedUp = car()
//1
function car(){
 var speed = 0
 return function (){
 speed++
 console.log(speed)
 }
}
var speedUp = car()
//2
function car(speed){
 return function (){
 speed++
 console.log(speed)
 }
}
var speedUp = car(3)
//3
function car(){
 var speed = arguments[0]
 return function (){
 speed++
 console.log(speed)
 }
}
var speedUp = car()
//4
function car(){
 var speed = 0
 return function (){
 speed++
 console.log(speed)
 }
}
//5 car可以不写,则为匿名函数 
var speedUp = (function car(speed){
 return function (){
 speed++
 console.log(speed)
 }
}
)(3)
ログイン後にコピー
クロージャーの関連ケース

次のコードの出力はどれくらいですか? 3を出力したい場合、コードをどのように修正すればよいでしょうか?

var fnArr = [];
for (var i = 0; i < 10; i ++) {
 fnArr[i] = function(){
 return i
 };
}
console.log( fnArr[3]() ) // 10
ログイン後にコピー

均等進化

ループのレベルが 2 つだけであると仮定します。

var fnArr = []
for (var i = 0; i < 2; i ++) {
 fnArr[i] = (function(j){
 return function(){
 return j
 } 
 })(i)
}
fnArr[3]()
//1
var fnArr = [] 
fnArr[0] = (function(j){
 return function(){
 return j
 } 
 })(0)
}
fnArr[1] = (function(j){
 return function(){
 return j
 } 
 })(1)
}
fnArr[3]()
//2
var a = (function(j){
 return function(){
 return j
 } 
 })(0)
}
var b = (function(j){
 return function(){
 return j
 } 
 })(1)
}
b()
//3
var a = (function(j){
 return function(){
 return j
 } 
 })(0)
}
function fn2(j){
 return function(){
 return j
 }
}
var b = fn2(1)
//4
var a = (function(j){
 return function(){
 return j
 } 
 })(0)
}
function fn2(j){
 return function(){
 return j
 }
 return f
}
var b = fn2(1)
//5
var a = (function(j){
 return function(){
 return j
 } 
 })(0)
}
function fn2(j){
 var j = arguments[0]
 function f(){
 return j
 }
 return f
}
var b = fn2(1)
ログイン後にコピー

変換後 (ステートメントの即時実行、進化プロセス)

var fnArr = []
for (var i = 0; i < 10; i ++) {
 fnArr[i] = (function(j){
 return function(){
 return j
 } 
 })(i)
}
console.log( fnArr[3]() ) // 3
var fnArr = []
for (var i = 0; i < 10; i ++) {
 (function(i){
 fnArr[i] = function(){
 return i
 } 
 })(i)
}
console.log( fnArr[3]() ) // 3
var fnArr = []
for (let i = 0; i < 10; i ++) {
 fnArr[i] = function(){
 return i
 } 
}
console.log( fnArr[3]() ) // 3
ログイン後にコピー

Encapsulate Car オブジェクト

var Car = (function(){
 var speed = 0;
 function set(s){
 speed = s
 }
 function get(){
 return speed
 }
 function speedUp(){
 speed++
 }
 function speedDown(){
 speed--
 }
 return {
 setSpeed: setSpeed,
 get: get,
 speedUp: speedUp,
 speedDown: speedDown
 }
})()
Car.set(30)
Car.get() //30
Car.speedUp()
Car.get() //31
Car.speedDown()
Car.get() //3
ログイン後にコピー

次のコードの出力はいくらですか? 0,1,2,3,4

for(var i=0; i<5; i++){
 setTimeout(function(){
 console.log(&#39;delayer:&#39; + i )
 }, 0)
}
ログイン後にコピー

を連続出力する方法 出力結果は、layer:5(5回連続出力)となります。 setTimeoutを実行すると、真ん中の部分でコードがハングします。 i のトラバースが完了するまでタスク キューを実行し、この時点で i = 5 が出力されるため、layer:5 が出力されます (5 回連続出力)

変更後

for(var i=0; i<5; i++){
 (function(j){
 setTimeout(function(){
 console.log(&#39;delayer:&#39; + j )
 }, 0)//1000-1000*j 
 })(i)
}
ログイン後にコピー

or

for(var i=0; i<5; i++){
 setTimeout((function(j){
 return function(){
 console.log(&#39;delayer:&#39; + j )
 }
 }(i)), 0) 
}
ログイン後にコピー

次のコードの出力はどれくらいですか?

function makeCounter() {
 var count = 0
 return function() {
 return count++
 };
}
var counter = makeCounter()
var counter2 = makeCounter();
console.log( counter() ) // 0
console.log( counter() ) // 1
console.log( counter2() ) // 0
console.log( counter2() ) // 1
ログイン後にコピー

配列を名前、年齢、および任意のフィールドで並べ替えるコードを完成させます

var users = [
 { name: "John", age: 20, company: "Baidu" },
 { name: "Pete", age: 18, company: "Alibaba" },
 { name: "Ann", age: 19, company: "Tecent" }
]
users.sort(byName) 
users.sort(byAge)
users.sort(byField(&#39;company&#39;))
ログイン後にコピー

回答

function byName(user1, user2){
 return user1.name > user2.name
}
function byAge (user1, user2){
 return user1.age > user2.age
}
function byFeild(field){
 return function(user1, user2){
 return user1[field] > user2[field]
 }
}
users.sort(byField('company'))
ログイン後にコピー

sum 関数を作成し、次の呼び出しメソッドを実装します

れー

以上がjsクロージャのコード例解説の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:segmentfault.com
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート