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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

作用域、执行环境、闭包(四)

發(fā)布時間:2023/12/2 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 作用域、执行环境、闭包(四) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文也同步發(fā)表在我的公眾號“我的天空

?

?

上一期我們已經介紹了閉包,由于閉包可以延長函數內部的變量的生存周期,因此我們可以將不需要暴露在全局的變量封裝成函數的內部變量,從而避免代碼污染。

?

譬如要實現一個簡單的累加器,為了保存每次累加的結果,因此聲明了一個全局變量total,代碼如下:

?

var total=0;
function add(t){
??? total =t;
??? alert(total);
}
total=2;
add(3);??????? //顯示5
add(5);??????? //顯示10
add(1);??????? //顯示11

?

但是在實際開發(fā)中,應盡量避免全局變量,因為全局變量可以在代碼的任何地方被調用,假設在其他地方,不小心更改了total的值的話,我們這個累加器就會出問題了。由于total值是只供函數add()使用的,因此希望total能被封閉在函數add()的內部,這樣,就無法從外部來改寫它了,我們使用閉包來實現,代碼如下:

?

function add(s){
??? var total=s;
??? return function(t){
?? ? ?? total =t;
??????? alert(total);
??? }
}
var a=add(2);
a(3);??????? //顯示5
a(5);??????? //顯示10
a(1);??????? //顯示11

?

通過閉包,將變量total封閉在函數add()中,外部無法訪問到,這樣就避免了被其他代碼隨意改寫的可能性。

?

由于閉包會將封閉在函數內部的局部變量賦予類似于全局變量的效果,因此在有些場景下需要特別注意,尤其是涉及到循環(huán)遍歷,來看以下代碼:

?

function createArray(){
??? var result=new Array();
??? for (var i=0;i<3;i ){
??????? result[i]=function(){
??????????? return i;
??????? }
??? }
}

?

這是一個創(chuàng)建數組數組的函數,從表面上看,每個函數應該都返回自己的索引值,因此創(chuàng)建的數組中,每個元素應該包含如下函數:

?

result[0]:function(){return 0}
result[1]:function(){return 1}
result[2]:function(){return 2}

?

但是實際上,數組中的每個元素只是包含:function(){return i},也就是說,當該函數執(zhí)行完畢后,返回的是這樣一個數組:

?

{
??? function(){return i},
??? function(){return i},
??? function(){return i}
}

?

而變量i由于存在于一個返回函數中,形成了閉包,所以當createArray()執(zhí)行完畢后,其執(zhí)行環(huán)境不會被銷毀,變量i得以保留,并且其值為3(這點很重要)。

?

因此,當我們使用createArray()來創(chuàng)建數組時,得到的效果就不是我們的預期,彈出的都為“3”:

?

var a=createArray();
for(var z=0;z<a.length;z ){
??? alert(a[z]());??? //均顯示為3
}

?

實際上該代碼無非就是重復執(zhí)行三遍以下代碼:

?

alert(function(){return 3}());


那么為了達到我們的預期,應該將createArray()函數做如下修改:

?

function createArray(){
??? var result=new Array();
??? for (var i=0;i<3;i ){
??????? result[i]=function(z){
??????????? return function(){
??????????????? return z;
??????????? };
??????? }(i)
??? }
}

?

分析以上代碼,我們將一個自執(zhí)行函數返回給了數組元素,在賦值的時候,變量z就是在賦值的那個時刻的i值,那么返回的數組中的元素便包含我們預期的函數:

?

result[0]:function(){return 0}
result[1]:function(){return 1}
result[2]:function(){return 2}

?

再一次執(zhí)行以下代碼,顯示就正常了:

?

var a=createArray();
for(var z=0;z<a.length;z ){
??? alert(a[z]());??? //依次顯示0、1、2
}


一定要注意的是,我們是把一個函數賦予了數組中的元素,而不是單個的值。因為在實際的應用中,返回函數的話,我們就可以在函數內做更多的事情。

?

看以下的實現,html有四個p標簽和4個div標簽,當單擊div標簽時相應的p標簽更改顏色,請注意這是一個面試中非常容易遇到的題目,代碼如下:

?

<body>
? <p>p1</p><p>p2</p><p>p3</p><p>p4</p>
? <div>div1</div><div>div2</div><div>div3</div><div>div4</div> ?
?</body>

? <script>
???? var d=document.getElementsByTagName("div");
?? ??? for(var i=0;i<d.length;i ){
?? ??? ? d[i].οnclick=function(num){
?? ??? ??? ? return function(){
?? ??? ??? ??? ?document.getElementsByTagName("p")[num].style.color="red";
?? ??? ??? ? };
?? ??? ? }(i);
?? ??? }
?</script>

?

如果直接寫成以下代碼的話,那么無論你單擊哪個div,程序總是會報錯,因為此時i的值為4,所以document.getElementsByTagName("p")[4]這個元素并不存在,導致引用錯誤。

?

?? for(var i=0;i<d.length;i ){
?? ???? d[i].οnclick=function(){
?? ??? ?? document.getElementsByTagName("p")[i].style.color="red";
? ?? ?};
?? }

?

最后我們要注意的是當需要返回函數內部的多個變量時,便不能采用返回匿名函數的方式了,可以采用以下的形式:

?

function setpepole(){
??? var name="李四";?? ?
??? var age=31;
??? return {
??????? getname:funcion(){
??????????? return name;?? ?
??????? },
??????? getage:function(){
??????????? return age;
??????? }
??? }
}
var a=setpepole();
alert(a.getname());???? //顯示“李四”
alert(a.getage());????? //顯示31

?

閉包系列就到此全部結束了!

?


更多專業(yè)前端知識,請上 【猿2048】www.mk2048.com

總結

以上是生活随笔為你收集整理的作用域、执行环境、闭包(四)的全部內容,希望文章能夠幫你解決所遇到的問題。

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