之前有寫過閉包符衔,作用域,this方面的文章糟袁,但現(xiàn)在想想當(dāng)時寫的真是廢話太多了判族,以至于繞來繞去的,讓新手反而更難理解了项戴,所以就有了此篇文章形帮,也好和閉包,作用域周叮,this告一段落辩撑。
第一個問題:什么是閉包?
我不想回答這個問題仿耽,但是我可以告訴你的是**閉包可以解決函數(shù)外部無法訪問函數(shù)內(nèi)部變量的問題**合冀。下面是一段沒有使用閉包的代碼:
function fn(){
var a = 10;
}
alert(a); //報錯了,因為a沒有定義项贺,雖然函數(shù)fn里面定義了a但是君躺,但是它只能在函數(shù)fn中使用。也就是作用域的問題开缎。
再看‘閉包可以解決函數(shù)外部無法訪問函數(shù)內(nèi)部變量的問題’這段話棕叫,好像有點意思,那么究竟閉包是怎么做的奕删,看下面代碼谍珊。
function fn(){
//定義了一個變量name
var name = '追夢子';
//我現(xiàn)在想在外部訪問這個變量name怎么辦呢?哈:不是有return,我把它返回出去砌滞,我再用個變量接收一下不就可以了侮邀,哈哈哈哈~~~~~ return name; } var name = fn();//接收fn返回的name值。 alert(name);//追夢子贝润;
·······這里的閉包就是利用函數(shù)的return绊茧。除了通過return還可以通過其他的幾種方法如下:
方法1:
function fn(){
var a = 0;
b = a;
}
alert(b)
這里利用了js的一個特性,如果在函數(shù)中沒有用var定義變量打掘,那么這個變量屬于全局的华畏,但這種方法多少有些不好。
方法2:
var f = null;
function fn(){
var a = 0;
f = function(){
a++;
f.a = a;
};
}
fn();
f();
alert(f.a);//1
f();
alert(f.a);//2
但好像也沒有那樣神奇對吧尊蚁?其實閉包還有一個很重要的特性亡笑。來看一個例子。
var lis= document.getElementsByTagName['li'];
//假如這段代碼中的lis.length = 5;
for(var i=0;i<lis.length;i++){
lis[i].onclick = function(){
alert(i);
};
}
最終結(jié)果是不管單擊哪個li元素都是彈5横朋。不信你試試仑乌。為什么呢∏俣В看下面分析晰甚。
for(var i=0;i<lis.length;i++){
} // i = 5對吧
lis[0].onclick = function(){
alert(i);
};
lis[1].onclick = function(){
alert(i);
};
lis[2].onclick = function(){
alert(i);
};
lis[3].onclick = function(){
alert(i);
};
lis[4].onclick = function(){
alert(i);
};
為什么會這樣呢,因為你for循環(huán)只是給li綁定事件决帖,但是里面的函數(shù)代碼并不會執(zhí)行啊厕九,這個執(zhí)行是在你點擊的時候才執(zhí)行的好吧?但是此時的i已經(jīng)是5了地回,所以所有的都打印出5來了扁远。
如果想解決這個問題我們可以使用閉包,閉包的特點不只是讓函數(shù)外部訪問函數(shù)內(nèi)部變量這么簡單刻像,還有一個大的特點就是通過閉包我們可以讓函數(shù)中的變量持久保持畅买。來看。
function fn(){
var num = 0;
return function(){
num+=1;
alert(num); }; } var f = fn(); f(); //1 f(); //2
如果你是初學(xué)者可能沒覺得這有什么绎速。OK皮获,讓你看個東西。
function fn(){
var num = 5; num+=1; alert(num); } fn(); //6 fn(); //6
為什么呢纹冤?因為函數(shù)一旦調(diào)用里面的內(nèi)容就會被銷毀洒宝,下一次調(diào)用又是一個新的函數(shù),和上一個調(diào)用的不相關(guān)了萌京,不過有個特殊的情況雁歌,看這:
function fn(){
var num = 0;
return function(){
num+=1;
alert(num); }; } var f = fn(); f(); //1 f(); //2
這段代碼很簡單,不要被它欺騙了知残,我們首頁定義了一個fn函數(shù)靠瞎,里面有個num默認(rèn)為0,接著返回了一個匿名函數(shù)(也就是沒有名字的函數(shù))。我們在外部用f接收這個返回的函數(shù)乏盐。這個匿名函數(shù)干的事情就是把num加1佳窑,還有我們用來調(diào)試的alert。
這里之所以執(zhí)行玩這個函數(shù)num沒有被銷毀是因為那個匿名函數(shù)的問題父能,因為這個匿名函數(shù)用到了這個num神凑,所以沒有被銷毀,一直保持在內(nèi)存中何吝,因此我們f()時num可以一直加溉委。
這里你可以看不懂了,之所以有這種感覺是因為js回收機制你不懂爱榕,強烈建議你看我之前的再次講解js中的回收機制是怎么一回事瓣喊。這篇文章。
關(guān)于閉包的知識就到這里了黔酥,如果你想看關(guān)于閉包的案例可以看這篇:從閉包案例中學(xué)習(xí)閉包的作用藻三,會不會由你。
而外:關(guān)于在for循環(huán)中綁定事件打印變量i是最后一次絮爷。
而外說一句:這里并不是說return就是閉包趴酣,這里只是強調(diào)return的重要性梨树,如果你還是一個新手建議你多看一些初級文章坑夯,在來看這篇文章,希望你會有新收獲抡四。寫這篇文章一開始我也說了它的目的是回顧一下當(dāng)初我沒有理解的地方柜蜈,當(dāng)初已經(jīng)理解的這篇文章并沒有過多的去講。
作用域竟然上面已經(jīng)講完了~~~
大前端 369451410歡迎你的加入指巡。
那就說一下this:
我們經(jīng)常用this淑履,但是也許你還不清楚它是什么吧?
lis[i].onclick=function(){this.style.border="1px solid #ccc";} ;
此時的this表示lis[?]它的引用藻雪。 這里的i不是i實際上是一個準(zhǔn)確的數(shù)字:如lis[2].onclick = function(){this.style.border="1px solid #ccc";}; this = lis[2] 秘噪;
簡單來說**this它始終引用一個對象。**
lis[2]它也一個對象勉耀,是一個HTMLElement對象指煎。
其實不管什么情況下它都會有對象的,這個你不用操心便斥,看
function fn(){
this.name = "追夢子";
}; fn(); alert(this.name);//追夢子 //當(dāng)然也可以這樣
alert(name);
雖然這段代碼中看似沒有對象至壤,但大錯特錯,因為瀏覽器環(huán)境中默認(rèn)就有一個window對象枢纠,因此你在函數(shù)中直接用this.name實際上這個this就表示window像街。
var json = {
name:'yyy',
fn:function(){alert(this.name)}
};
json.fn(); // yyy;
fn屬于json,所以this實際上就是json。