日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

JavaScript作用域闭包简述

發布時間:2025/3/21 javascript 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JavaScript作用域闭包简述 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

作用域

  技術一般水平有限,有什么錯的地方,望大家指正。

  作用域就是變量起作用的范圍。作用域包括全局作用域,函數作用域以塊級作用域,ES6中的let和const可以形成塊級作用域。

  除了塊級作用域,在函數外面聲明的變量可以在任何一個地方被訪問到,這些變量的作用域都是全局作用域,全局作用域中的變量可以再任何一個地方使用:

var a = "zt"; function fn1(){console.log(a); } function fn2(){console.log(a); } fn1(); fn2();

  在函數里面聲明的變量只能在當前函數內使用,這些變量的作用域我們稱為函數作用域,只在當前函數內有效:

function fn1(){var a = "zt";console.log(a); } function fn2(){console.log(a) } fn1(); fn2();//報錯提示a沒有定義

  函數內定義的變量只在當前函數內有效,在函數以外的地方是不能被訪問到的,fn2函數內沒有定義a,全局作用域中也沒有a使用一個不存在的變量所以報錯。

作用域鏈

  作用域是可以嵌套的比如在全局作用域里面創建一個函數,函數里面可以在創建一個函數,這樣就發生了作用域的嵌套,作用域鏈可以把作用域鏈接起來。當使用一個變量的時候,會優先在當前作用域內去尋找變量,如果當前作用域內不存在就會去上層作用域去尋找一直到全局作用域,如果還不能找到變量就會報錯。  

var a = "global"; function fn1(){console.log(a); } fn1();

作用域是靜態的

  我們先看一個例子:

var flag = "outer";function demo(){var flag = "inner";function inner(){console.log(flag);}return inner;}var fn = demo();fn();//inner var flag = "outer";function demo(){var flag = "inner";fn();}function fn(){console.log(flag);}demo();//outer

  通過這兩個例子我們可以看出函數的作用域是靜態的,一個函數不管在哪被調用,它的作用域都是聲明時的作用域。函數的作用域在聲明時就已經被創建,在調用函數時會去訪問他已經創建的作用域。

閉包

  閉包在MDN中的定義為:閉包是指那些可以訪問獨立變量的函數,所以在定義上我們可以把所有的函數都看做是閉包。閉包即密閉的空間,我們可以很自然的想到函數,因為函數就會生成一個密閉的空間,如果函數想稱為一個閉包只需要在使用一個外部變量即可(使用外部變量的函數就是閉包)。通過閉包可以給我們帶來一些便利,就是可以在高等級的作用域使用低等級作用域中的變量:

function demo(){var flag = "test";return function(){console.log(flag);}}demo()();

  我們把demo函數里面的函數通過return使其可以在外部使用,我們已經說過作用域都是靜態的,這樣我們在外部使用return的函數時,就可以看到我們在全局作用域中調用函數最后輸出了demo函數里面的"test"。

  這樣我們可以做一些更有意義的事:

var data = [];function demo(){var data = [];return{add:function(a){data.push(a);},print:function(){console.log(data);}}}var tool = demo();tool.add(1);tool.add(2);tool.add(3);tool.print();//[1, 2, 3]

  我們可以利用demo函數里面的data來存儲我們的信息而且不用擔心它被破壞(demo里面的data被私有化),而且我們也可以在外部在聲明一個同名的data來存儲別的信息,這兩個不會產生任何沖突。

  閉包也可以幫我們解決一些小問題:

for(var i=0;i<4;i++){setTimeout(function(){console.log(i);});}

  我們預期的結果是打印當前循環的i值結果輸出全是4。先解釋一下出現這么情況的原因:JS是一種單線程的語言,而setTimeout是異步的,只有當我們的代碼執行完成以后setTimeout的處理函數才會執行,而執行的時候i的值已經是4了所以最終的輸出全是4。

  我們可以通過閉包來解決這一問題:

for(var i=0;i<4;i++){(function(i){setTimeout(function(){console.log(i)})}(i))}

  閉包可以形成一個獨立的作用域這樣每次循環都會有一個獨立的函數作用域,循環完成后雖然i的值仍然是4但是setTimeout的處理函數在尋找i的時候會優先找到作為參數的i,而每一個參數i都表示當次循環的i,利用閉包我們可以完美的解決這種問題。

  在我們實際開發的過程中,遇到這種情況我們就可以通過閉包來解決,我們所說的"這種情況"通常有三個特點:

  1.首先有一個循環

  2.循環里面會創建函數,并且函數是延后執行的

  3.這些延后執行的函數會使用一個共同的變量,并且這個共同的變量和當前的循環值有關系

  我們按照這個規律套一下上面的代碼:

  循環有了,每次循環也會生成一個函數,這些函數也都是在循環完成后才能執行,而且每一個函數都使用共同的i,而i就是當前的循環值,正好符合我們的三個特點。我們通過(function(){}())這種方式(匿名函數自執行)來形成一個閉包達到我們預期的目的。

  更深層次的了解,可以在網上查閱相關資料。

轉載自網絡

轉載于:https://www.cnblogs.com/wenJiaQi/p/6034138.html

總結

以上是生活随笔為你收集整理的JavaScript作用域闭包简述的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。