javascript中的作用域和閉包詳解
一、JavaScript作用域
JavaScript變量實(shí)際上只有兩種作用域,全局變量和函數(shù)的內(nèi)部變量。在函數(shù)內(nèi)部任何一個(gè)地方定義的變量(var scope)其作用域都是整個(gè)函數(shù)體。
全局變量:指的是window對象下的對象屬性。
作用域劃分:基于上下文,以函數(shù)進(jìn)行劃分的,而不是由塊劃分的。
強(qiáng)調(diào)兩點(diǎn):
1. 在同一作用域中,JavaScript是允許變量的重復(fù)定義,并且后一個(gè)定義將覆蓋前一個(gè)定義。
2. 函數(shù)內(nèi)部如果不加關(guān)鍵字var而定義的變量,默認(rèn)為全局變量。
var scope="global";
function t(){
console.log(scope); //"global"
scope="local"
console.log(scope); //"local"
}
t();
console.log(scope); //"local"
var scope="global";
function t(){
console.log(scope); //"undefined"
var scope="local"
console.log(scope); //"local"
}
t();
console.log(scope); //"global"
在變量解析過程中首先查找局部的作用域,然后查找上層作用域。在第一段代碼的函數(shù)當(dāng)中沒有定義變量scope,于是查找上層作用域(全局作用域),進(jìn)而進(jìn)行輸出其值。但是在第二段代碼的函數(shù)內(nèi)定義了變量scope(無論是在console之后還是之前定義變量,都認(rèn)為在此作用域擁有變量scope),于是不再向上層的作用域進(jìn)行查找,直接輸出scope。但是不幸的是此時(shí)的局部變量i并沒有賦值,所以輸出的是undefined。
//所以根據(jù)函數(shù)作用域的意思,可以將上述第二段代碼重寫如下:
var scope="global";
function t(){
var scope;
console.log(scope);
scope="local"
console.log(scope);
}
t();
由于函數(shù)作用域的特性,局部變量在整個(gè)函數(shù)體始終是由定義的,我們可以將變量聲明”提前“到函數(shù)體頂部。
var b; //第1步
function fun(){
b = "change";
}
alert(b);//輸出undefined,由于第1步只定義未賦值
var b; //第1步
function fun(){
b = "change";
}
fun(); //調(diào)用上述函數(shù)
alert(b); //輸出change
當(dāng)使用var聲明一個(gè)變量時(shí),創(chuàng)建的這個(gè)屬性是不可配置的,也就是說無法通過delete運(yùn)算符刪除。
二、作用域?qū)嵗?/strong>
<html>
<head>
<script type="text/javascript">
function buttonInit(){
for(var i=1;i<4;i++){
var b=document.getElementById("button"+i);
b.addEventListener("click",function(){ alert("Button"+i);},false);
}
}
window.onload=buttonInit;
</script>
</head>
<body>
<button id="button1">Button1</button>
<button id="button2">Button2</button>
<button id="button3">Button3</button>
</body>
</html>
當(dāng)注冊事件結(jié)束后,i的值為4,當(dāng)點(diǎn)擊按鈕時(shí),事件函數(shù)即function(){ alert("Button"+i);}這個(gè)匿名函數(shù)中沒有i,根據(jù)作用域鏈,所以到buttonInit函數(shù)中找,此時(shí)i的值為4,所以彈出”button4“。
三、javaScript閉包
在js中,閉包主要涉及到j(luò)s的幾個(gè)其他的特性:作用域鏈,垃圾(內(nèi)存)回收機(jī)制,函數(shù)嵌套,等等。
1. 作用域鏈:簡單來說,作用域鏈就是函數(shù)在定義的時(shí)候創(chuàng)建的,用于尋找使用到的變量的值的一個(gè)索引,而他內(nèi)部的規(guī)則是,把函數(shù)自身的本地變量放在最前面,把自身的父級函數(shù)中的變量放在其次,把再高一級函數(shù)中的變量放在更后面,以此類推直至全局對象為止。當(dāng)函數(shù)中需要查詢一個(gè)變量的值的時(shí)候,js解釋器會去作用域鏈去查找,從最前面的本地變量中先找,如果沒有找到對應(yīng)的變量,則到下一級的鏈上找,一旦找到了變量,則不再繼續(xù)。如果找到最后也沒找到需要的變量,則解釋器返回undefined。
2. Javascript的垃圾回收機(jī)制:在Javascript中,如果一個(gè)對象不再被引用,那么這個(gè)對象就會被GC回收。如果兩個(gè)對象互相引用,而不再被第3者所引用,那么這兩個(gè)互相引用的對象也會被回收。因?yàn)楹瘮?shù)a被b引用,b又被a外的c引用,這就是為什么函數(shù)a執(zhí)行后不會被回收的原因。構(gòu)建一個(gè)閉包,這些變量將不會被內(nèi)存回收器所回收,只有當(dāng)內(nèi)部的函數(shù)不被調(diào)用以后,才會銷毀這個(gè)閉包,而沒有任何一個(gè)閉包引用的變量才會被下一次內(nèi)存回收啟動(dòng)時(shí)所回收。
3. 有了閉包,嵌套的函數(shù)結(jié)構(gòu)才可以運(yùn)作
四、利用js閉包實(shí)現(xiàn)循環(huán)綁定事件
<html>
<head>
<title>閉包</title>
</head>
<body>
<ul id="list">
<li>第1條記錄</li>
<li>第2條記錄</li>
<li>第3條記錄</li>
<li>第4條記錄</li>
<li>第5條記錄</li>
<li>第6條記錄</li>
</ul>
<script type="text/javascript">
function tt(nob) {
this.clickFunc = function() {
alert("這是第" + (nob + 1) + "記錄");
}
}
var list_obj = document.getElementById("list").getElementsByTagName("li"); //獲取list下面的所有l(wèi)i的對象數(shù)組
for (var i = 0; i<= list_obj.length; i++){
console.log(list_obj[i])
list_obj[i].onmousemove = function(){
this.style.backgroundColor = "#cdcdcd";
}
list_obj[i].onmouseout = function() {
this.style.backgroundColor = "#FFFFFF";
}
//list_obj[i].onclick = function() {
// alert("這是第" + i + "記錄"); //不能正常獲取 alert出來的都是:“這是第6記錄”
//}
var col = new tt(i); //調(diào)用tt函數(shù)
list_obj[i].onclick = col.clickFunc; //執(zhí)行clickFunc函數(shù)
}
</script>
</body>
</html>
以上就是本文的全部內(nèi)容,希望對大家學(xué)習(xí)javascript程序設(shè)計(jì)有所幫助。
相關(guān)文章
js實(shí)現(xiàn)屏幕自適應(yīng)局部代碼分享
這篇文章主要介紹了js實(shí)現(xiàn)屏幕自適應(yīng)局部代碼分享,需要的朋友可以參考下2015-01-01
點(diǎn)擊提交按鈕后按鈕變灰色不可用狀態(tài)的三種方法
當(dāng)點(diǎn)擊提交后,提交按鈕變灰色不可用,這樣可有效防止重復(fù)提交,本代碼就是實(shí)現(xiàn)這樣一個(gè)功能2013-09-09
純js實(shí)現(xiàn)仿QQ郵箱彈出確認(rèn)框
仿QQ郵箱的彈出層,彈出確認(rèn)框,主要是用火狐的firebug把html和css扣了下來,沒有做封裝,就定義了一個(gè)拖動(dòng)事件. 大家可以封裝自己的彈出窗,嘿嘿!2015-04-04
JS實(shí)現(xiàn)頁面中所有img對象添加onclick事件及新窗口查看圖片的方法
這篇文章主要介紹了JS實(shí)現(xiàn)頁面中所有img對象添加onclick事件及新窗口查看圖片的方法,涉及JS頁面元素遍歷及屬性動(dòng)態(tài)操作相關(guān)技巧,需要的朋友可以參考下2016-12-12
javascript實(shí)現(xiàn)隨機(jī)生成DIV背景色
這篇文章主要介紹了javascript實(shí)現(xiàn)隨機(jī)生成DIV背景色的具體代碼,如何設(shè)置DIV背景色為隨機(jī)色,感興趣的小伙伴們可以參考一下2016-06-06
html中鼠標(biāo)滾輪事件onmousewheel的處理方法
下面小編就為大家?guī)硪黄猦tml中鼠標(biāo)滾輪事件onmousewheel的處理方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-11-11

