亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

JavaScript必知必會(九)function 說起 閉包問題

2019-11-20 09:45:16
字體:
來源:轉載
供稿:網友

function

函數格式

function getPrototyNames(o,/*optional*/ a){a = a || [];for(var p in o){a.push(p);}return a;} 

caller

func.caller 返回函數調用者

function callfunc(){if(callfunc.caller){alert(callfunc.caller.toString());}else{alert("沒有函數調用");}}function handleCaller(){callfunc();}handleCaller();//返回 handlercallfunc();//沒有函數調用,返回null,執行了《沒有函數調用》 

callee

匿名方法遞歸調用

alert( (function (x) {if (x <= ) return ;return x * arguments.callee(x - );}()));// 

scope

作用域大家都不陌生,今天就來說說閉包問題,深刻吃透閉包問題。

<script>var global = "global scope";//這個是全局的作用域function scope(){var scope = "local scope";//這個是局部的作用域return scope;//返回的scope,是局部的變量}</script> 

  1、:定義的全局變量也能在函數內部訪問。當定義的局部變量和全局變量名字相同時,局部變量的就會隱藏全局變量,不會破壞全局變量的值。

var scope = "global scope";function f(){var scope = "local scope";return scope;}alert(f());//local scopealert(scope);//global scope; 

  上面確實是很容易理解,對吧。

2、 全局變量可以不用var聲明,但是局部變量必須使用var聲明,如果局部變量不使用var聲明,編譯器會默認這個是個全局變量。

<span style="line-height: .; font-family: verdana, Arial, Helvetica, sans-serif; font-size: px; background-color: rgb(, , );">  </span> scope = "global scope";function f(){scope = "local scope";return scope;}alert(f());//local scopealert(scope);//local scope

  但是全局變量不使用var聲明,也僅限非嚴格模式,如果使用嚴格模式的話,會報錯誤

<script>"use strict";scope = "global scope";function f(){scope = "local scope";return scope;}alert(f());//local scopealert(scope);//local scope</script>

所以建議大家聲明變量時,千萬不要省略var,可以避免不必要的麻煩。

3、 聲明提前,也是可以滴。什么叫什么提前。

<script>"use strict";scope;console.log(scope);var scope = "global scope";console.log(scope);</script> 

這個可能大家看出第一個打印undefined ,是呀還沒有給他賦值, 下面賦值可定打印global scope了。

這樣理解并沒有錯,但是為什么會這樣的呢,一個變量不是應該先定義才可以使用的嗎?

這里給大家說下作用域鏈,JavaScript是基于詞法作用域的語言。

1、作用域鏈是一個對象或者鏈表,這組代碼中定義了這段代碼"作用域中“的變量。當JavaScript需要查找變量scope時,就會從鏈中的第一個對象開發查找,如果第一個對象為scope,則會直接返回這個對象的值,如果不存在繼續第二對象開始查找,直到找到。如果在作用域鏈上未查到該變量,則會拋出一個錯誤。

我們可以這個作用鏈可以這樣表示:查找 scope->window(全局對象)很顯然后面是有定義scope的。但是并沒有做賦值操作,后面才做賦值操作,所以此時值為undefined.

4、這個比較具有迷惑性了,大家猜想下打印的值是什么?

<script>"use strict";var scope = "global scope";function f() {console.log(scope);var scope = "local scope";console.log(scope);}f();</script>

看到這段代碼:如果你粗心大意的話,很有可能會寫出錯誤的答案:

1、gobal scope

2、local scope

分析: 聲明了全局變量,在函數體中時,第一個表示全局變量,所以打印global,第二定義了局部的變量,覆蓋掉了全局的scope,所以打印local scope。

這樣的分析在C# java ,完全正確。但是這里分析確實錯誤的。

這說明這個問題前,我們先看一個問題。

這句話很重要:全局變量在程序中始終都是有定義的。局部變量在聲明它的函數體以及其所嵌套的函數內始終是定義的。

如果你是從事高級語言工作開始接觸JavaScript 有點不適應其作用域的定義。我也是這樣的。我們來看一個例子:

<script>var g = "global scope";function f(){for(var i=;i<;i++){for(var j=;j<;j++){;}console.log(j);}console.log(i);}console.log(g);f();</script>

  打印的結果是什么?

大家看到{} 表示語句塊,語句塊在一塊作用域,所以大家可能猜想,j、i值已經在內存釋放掉了,所以結果肯定是undefined.

真實的結果可能令你失望,

結果為什么會是這樣,我開始的表情和你一樣。

這時查看我讓你記住的那句話。。。全局變量在程序中始終都是有定義的。局部變量在聲明它的函數體以及其所嵌套的函數內始終是定義的。

確切的說函數的參數 也是屬于局部變量的范疇。這句話也很重要?。?!

那句話大概意思說,只要是在函數內部定義的變量,在整個函數內都是有效的。所以結果也就不難理解了。在回過頭看我們的那個問題,你理解了嗎?

作用鏈還有以下定義:

1、作用鏈是有一個全局對象組成。

2、在不包含嵌套的函數體內,作用鏈上有兩個對象,第一個定義了函數參數和局部變量的對象,第二個是全局對象。

3、在一個嵌套的函數體內,作用鏈上至少包含三個對象。

當定以一個函數的時候,就會保存一個作用域鏈。

當調用這個函數時,它就會創建一個新的對象來存儲它的局部變量,并將這個對象添加到保存的作用鏈上。同時創建一個新的更長的表示函數調用的作用鏈。

對于嵌套的函數,當調用外部函數時,內部函數又會重新定義一遍。因為每次調用外部函數的時候,作用鏈都是不同的。內部函數在每次定義的時候都有微妙的差別,每次調用的外部函數時,內部函數的代碼都是相同的,而且關聯的代碼的作用域也是不同的。

閉包

搞了這么久終于要講了,但是再將之前我們在來分析下作用域。

<script>var nameg="global"var g = function f() {console.log(name);function demo(){console.log("demo="+name);}var name = "";function demo() {var name = "";console.log("demo=" + name);}function demo() {console.log("demo=" + nameg);}demo();demo();demo();};g();</script>

  我們按照作用鏈來分析:

調用demo0, demo0()->查找name,未找到->f()查找,返回

調用demo1,demo1()->查找name,找到,返回

調用demo2,demo2()->查找nameg,未找到->f()查找nameg,未找到->window查找nameg找到,返回。

看這個例子:

<script>function f(){var count = ;return { counter:function() {return count++;},reset:function(){return count = ;}}}var d = f();var c = f();console.log("d第一次調用:"+ d.counter());//console.log("c第一次調用:"+ c.counter());// 互不影響console.log("d第一次調用:"+ d.reset());//console.log("c第二次調調用"+ c.counter());//</script>

  這個例子上大家可以看到,我做了一個計數和置零的操作。

創建了兩個f的對象實例d c,各有自己的作用域鏈,所以其值互不影響。當c第二次調用時,count值被保存了,因為c對象并未被銷毀。明白這個例子后,后面的例子才比較好懂。

這個過程,大家應該十分明了了。那么現在我們來看閉包問題。我設置四個按鈕,點擊每個按鈕就返回響應的名字。

<body><script>function btnInit(){for(var i=;i<;i++){var btn = document.getElementById("btn" + i);btn.addEventListener("click",function() {alert("btn" + i);});}}window.onload= btnInit;</script><div><button id="btn">Btn</button><button id="btn">Btn</button><button id="btn">Btn</button><button id="btn">Btn</button></div></body>

  點擊運行,結果卻是都是btn5;

我們用剛才的分析在坐下,首先要調用匿名函數->查找i,未找到->btnInit(),找到i在for循環中。找到。我們知道只有函數調用結束才釋放,for中的i總是可見的,所以保留了最后的i值。那么如何解決呢。

解決i值在函數中不是總是可見的,那么我們就要使用函數的嵌套了,然后把i值傳進去。

function btnInit(){for(var i=;i<;i++){(function (data_i) {var btn = document.getElementById("btn" + data_i);btn.addEventListener("click", function () {alert("btn" + data_i);});}(i));}}

  看修改后的代碼,首先執行第一次for,創建了一個對象,我們首先是執行匿名函數->data_i,未找到->function(data_i)找到,然后再次執行for有創建一個對象,閉包規則說的互不影響。所以能得出正確的結果。

以上所述是小編給大家介紹的 JavaScript必知必會(九)function 說起 閉包問題的相關知識,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對武林網網站的支持!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
在线国产精品播放| 亚洲精品国产综合久久| 欧美日韩加勒比精品一区| 久久精品91久久香蕉加勒比| 欧美午夜激情在线| 91久久国产精品| 91av在线精品| 日本一区二区在线播放| 国产精品视频区1| 国产精品日韩一区| 亚洲美女在线观看| 欧美亚洲成人免费| 97碰在线观看| 成人天堂噜噜噜| 欧美日韩在线视频一区二区| 深夜福利91大全| 亚洲美女动态图120秒| 亚洲成人av片在线观看| 午夜精品福利电影| 亚洲国产成人久久综合一区| 久久久精品中文字幕| 亚洲精品短视频| 国产视频精品自拍| 国产视频自拍一区| 欧美猛交ⅹxxx乱大交视频| 日韩成人中文电影| 欧美激情啊啊啊| 亚洲综合在线播放| 疯狂做受xxxx高潮欧美日本| 国产精品精品国产| 国产亚洲人成网站在线观看| 色偷偷偷综合中文字幕;dd| 午夜精品免费视频| 亚洲精品欧美一区二区三区| 欧美日韩高清在线观看| 成人午夜高潮视频| 岛国av午夜精品| 一区二区三区美女xx视频| 精品久久久久久久中文字幕| 中文字幕国产精品久久| 成人深夜直播免费观看| 一区二区日韩精品| 国产精品 欧美在线| 久热在线中文字幕色999舞| 精品丝袜一区二区三区| 欧美中在线观看| 国产精品久久久久av免费| 欧美电影在线播放| 久久国产精品久久国产精品| 91av在线播放视频| 国产精品久久久久久久久久久久| 久久久久这里只有精品| 亚洲国产成人精品久久久国产成人一区| 久久久久久久香蕉网| 亚洲美女在线观看| 国产91精品黑色丝袜高跟鞋| 91亚洲精品在线| 精品福利免费观看| www.日韩av.com| 国产91成人在在线播放| 九九热r在线视频精品| 亚洲欧美日韩精品| 91国偷自产一区二区三区的观看方式| 亚洲精品日韩在线| 国产日韩欧美日韩大片| 庆余年2免费日韩剧观看大牛| 亚洲男人的天堂网站| 日韩第一页在线| 国产日韩精品入口| 久久久亚洲成人| 日韩在线欧美在线国产在线| 亚洲全黄一级网站| 97香蕉久久超级碰碰高清版| 久久久久久久久久久91| 狠狠色狠色综合曰曰| 久久精品久久久久久| 97国产一区二区精品久久呦| 成人午夜在线观看| 精品国内产的精品视频在线观看| 国产精品第3页| 国产欧美亚洲精品| 亚洲欧美国产一本综合首页| 午夜精品理论片| 久久久99免费视频| 久久精品国产亚洲精品2020| 久久人人爽亚洲精品天堂| 97超视频免费观看| 欧美日韩在线视频首页| 国产午夜精品美女视频明星a级| 57pao成人国产永久免费| 欧美大胆在线视频| 欧美另类老肥妇| 国产一区二区丝袜高跟鞋图片| 国产精品亚洲一区二区三区| 欧美激情一区二区三区成人| 国产精品久久国产精品99gif| 久久国产精品影片| 欧美性视频网站| 91久久精品一区| 成人黄色生活片| 亚洲精品自拍偷拍| 欧美性色19p| 亚洲第一网站免费视频| 91精品成人久久| 欧美一二三视频| 久久精品成人一区二区三区| 日韩网站免费观看高清| 久久久亚洲福利精品午夜| 国产精品视频男人的天堂| 久久成人免费视频| 日韩欧美在线视频日韩欧美在线视频| 欧美视频中文字幕在线| 欧美老肥婆性猛交视频| 欧美精品久久久久久久| 日韩欧美一区二区三区| 亚洲va欧美va在线观看| 伊人成人开心激情综合网| 92看片淫黄大片看国产片| 欧美性xxxxx| 亚洲成人久久一区| 91免费人成网站在线观看18| 亚洲午夜女主播在线直播| 久久久久久999| 日韩欧美高清在线视频| 亚洲人成电影在线| 91精品久久久久久久| 亚洲精品免费在线视频| 中文字幕九色91在线| 丰满岳妇乱一区二区三区| 国产啪精品视频网站| 亚洲影视九九影院在线观看| 国产美女久久精品| 亚洲精品91美女久久久久久久| 欧美国产日韩一区二区| 92看片淫黄大片看国产片| zzijzzij亚洲日本成熟少妇| 欧美最猛性xxxx| 国内精品久久久久久影视8| 国产成人极品视频| 久久精品免费播放| 久久国产精品偷| 日本不卡视频在线播放| 久久全球大尺度高清视频| 亚洲精品动漫久久久久| 欧美人在线视频| 亚洲第一天堂无码专区| 日韩在线视频免费观看高清中文| 国产精品久久久久久久久久久久久| 国产精品永久免费| 伦理中文字幕亚洲| 一区二区三区高清国产| 不卡av电影院| 成人网在线观看| 欧美成人久久久| 久久精品电影网| 91国语精品自产拍在线观看性色| 久热国产精品视频| 亚洲国产天堂网精品网站| 国产亚洲激情在线| 91精品综合久久久久久五月天| 国产剧情日韩欧美| 性亚洲最疯狂xxxx高清| 亚洲理论电影网| 成人免费xxxxx在线观看|