Javascript知識分享。


最近在讀大叔譯的javascript編程精解這本書,確實是本好書,大愛。
以前對javascript某些概念迷迷糊糊,雖然知道怎么回事,但一直弄不明白其中的原因...


那么就先拿以前一直弄不明白的這道題講講吧,如下:

例1:

< href ="javascript:;" >點我 </ a > /
< href ="javascript:;" >點我 </ a > /
< href ="javascript:;" >點我 </ a >
< script  type ="text/javascript" >
var  atags  =  document.getElementsByTagName( ' a ' );
for  ( var  i  =   0 , max  =  atags.length; i  <  max; i ++ ) {
    atags[i].onclick 
=   function () {
        alert(i);
    }
}
</ script >

預期結果可能是想彈出 0,1,2。可惜的是都彈出了:3
如果你一搜,一般會有這樣的解決辦法,如下面:

例2:

< script  type ="text/javascript" >
var  atags  =  document.getElementsByTagName( ' a ' );
for  ( var  i  =   0 , max  =  atags.length; i  <  max; i ++ ) {
    (
function (index) {
        atags[i].onclick 
=   function () {
            alert(index);
        }
    })(i);
}
</ script >

 

分析下兩個例子的運行情況,首先了解一下javascript的幾個知識點:

1、作用域
2、閉包
3、自執行函數。
4、值類型和引用類型

 

我來引用一下最近讀這本書的幾句精解:

1、JavaScript唯一能創建新作用域的地方是 function
2、包裹一些局部變量的一個函數叫做一個閉包
3、自執行函數表達式這個大家應該都很清楚了,不清楚就去看下大叔的:即調用的函數表達式
4、這個也應該清楚吧,我說下吧:Number Boolean String 在 js 里屬於值類型,對像屬於引用類型,如下例:

< script  type ="text/javascript" >
function  changeValue(value) {
    value 
=   5 ;
}
function  changeObj(objValue) {
    objValue.i 
=   5 ;
}

var  i  =   0 ;
var  obj  =  { i:  0  };

changeValue(i);
changeObj(obj);

alert(i); 
// 0
alert(obj.i);  // 5
</ script >

 

到這里,上面的幾個知識點,應該都比較清楚了。
先來看作用域:JavaScript唯一能創建新作用域的地方是 function,那么就是說像 for 這類的是不會產生自己的作用域的。我們來實驗一下。

for (var i = 0; i  <  5 ; i++) {
    //這里干點啥
}
alert(i); //5

 

可以看出,for里的定義確實不會產生自己的作用域,這個其實也就是在全局里定義了一個變量i,就像以下這樣:

var i = 0;
for (; i  <  5 ; i++) {
    
}
alert(i); //5

 

貼心提示:從上面的例子我們能看出,一定要理解作用域,否則很容易發生沖突。比如:

//a某在這寫了個變量 i
var i = 9527;
//b某在這寫了這貨
for (var i = 0; i  <  5 ; i++) {
    //
}
//a某在這果斷悲劇了。
alert(i);

 

那么我們再來看上面的例1,這時我們應該很清楚為什么會全部彈出:3了。
因為所有鏈接彈出的是全局變量i,而全局變量i在循環完后的值是3,如下:

< script  type ="text/javascript" >
var  atags  =  document.getElementsByTagName( ' a ' );
for  ( var  i  =   0 , max  =  atags.length; i  <  max; i ++ ) {
    atags[i].onclick 
=   function () {
        alert(i);
    }
}
alert(i); 
// 這里顯示:3
</ script >

 

例2:這里如果理解上面的一些知識,例2也就不難理解了。

匿名自執行函數表達式收到index,因為是值類型參數,所以匿名函數內部重新分配這個局部變量。

然后鏈接 onclick 綁定的那個事件函數就是匿名函數的內部函數,並引用了匿名函數的那個局部變量(index)(這里是產生了一個閉包的)

最后的結果就是三個鏈接分別顯示了三個匿名函數的局部變量。

[注:這里感謝 @Justany_WhiteSnow 的指點,原先我認為例2沒有產生閉包,我說錯了,差點誤導大家,這里及時做個修改吧。並且把 @Justany_WhiteSnow 的正確見解在這里與大家分享下。]

 

另外我們還可以把那個自執行函數拿到外面:

< script  type ="text/javascript" >
function  bind(index) {
    atags[index].onclick 
=   function () {
        alert(index);
    }
}
var  atags  =  document.getElementsByTagName( ' a ' );
for  ( var  i  =   0 , max  =  atags.length; i  <  max; i ++ ) {
    bind(i);
}
</ script >

 

好,這篇就到這了,有什么說錯的地方歡迎大家指正。

轉載請注明出處,謝謝。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM