javascript中的this

javascript裡避免不瞭用到this,不過this的作用域scope問題常常會不經意間發送變化,導致程序出現錯誤或異常。
這裡隻對this做一些簡單的總結,更詳細的行為還需要大傢去琢磨。
this都是用在函數function裡的(廢話…)。這裡要說明一點,js裡的函數就是一個普通函數(沒有成員函數這一說法,準確的說),無論它定義在哪裡。
所以一個函數可以綁定到任何對象上去用,這時成這個被綁定的對象為該函數的owner。ok,函數裡的this就是指向他的owner的。
this的多變就是由於他的owner常常發生變化。舉個例子:
< script type = "text/javascript" >
    var o = {
        _name : 'o' , // used for debug
        foo : function (){
            console . log ( this . _name );
        }
    }
   
    o . foo ();
</ script >

這裡o.foo就是一個函數(應該叫函數指針,指向一個函數function(){console.log(this._name);})。那麼執行 o.foo()的時候,foo(確切說是foo指向的函數)的owner就是o,裡面的this也是o,運行結果會打印'o';
為什麼說是函數指針?再繼續這個例子:
< script type = "text/javascript" >
    var fn = o . foo ;
    fn ();
</ script >
      這裡fn = o.foo並不是系統把o.foo這個函數copy給瞭fn,而是copy瞭o.foo的指針值,讓fn也指向函數funtion(){console.log(this._name);}。
這時候執行fn什麼效果呢?fn(again,確切說是fn指向的函數)“沒瞭”owner,這時系統就會把window這個全局對象傳給this,也就是說fn(不again瞭)的owner是window。
因為window裡並沒定義_name屬性,這時會輸出undefined。再測試一下,給window添加個熟悉_name;
        < script type = "text/javascript" >
            window . _name = 'window' ;
            fn ();
        </ script >
        OK,上面說瞭函數裡的this到底指向的那個對象:執行時的owner。下面看看this為何會在實際應用中變化莫測。
根本原因很簡單,他的owner變瞭,像上面的o.foo和fn兩個例子就可以說明。以下舉幾個例子來說它經常的變化方式:
1. 對象裡的函數(你知道這麼說是不對的)調用瞭其他對象的函數,這時this就會變化
        < script type = "text/javascript" >
            // 例如常用的ajax
            var o2 = {
                xhr : null ,
                execute : function (){
                    xhr . onreadystatuschange = function (){
                        this . _traceXhr ( xhr ); // error here! 'this' is xhr now
                    }
                },
                _traceXhr : function ( _xhr ){
                    console . log ( _xhr );
                }
            }
        </ script >
        這裡的錯誤比較明顯瞭吧,function() {this._traceXhr(xhr);}是個函數,這時候是綁定到xhr上運行的,那裡面的this自然就指向xhr而不再是o2。
正確的寫法是o2._traceXhr(this);    (ps,實際的應用中可能是這樣的,一般會定義一個“類”,噢o2隻是這個類的實例,那麼定義類的時候需要這樣寫:
        < script type = "text/javascript" >
function ClazzO (){
}

ClazzO . prototype . xhr = null ;
ClazzO . prototype . execute = function (){
var _self = this ;
xhr . onreadystatuschange = function (){
_self . _traceXhr ( this );
}
}
ClazzO . prototype . _traceXhr = function ( _xhr ){
console . log ( _xhr );
}
</ script >
        execute裡用一個臨時變量保存一下善變的this,防止到瞭onxxxchange裡面的時候找不到他瞭。
主要是這一類問題導致this的變化,另外還有一些是和dom對象聯系在一起的

2. dom對象event裡的this
a: <input type = "button" id = "a" onclick = " javascript : console . log ( this . value ) " value = "click me a" />
這種寫法輸出結果和我們想的一樣:click this。但有些同學就提意見瞭,在html裡面夾雜太多的js代碼不好,而且有時由於函數太復雜含有' or "導致根本不能寫在這裡面,最好抽出來放到一個函數裡:
b: <input type = "button" id = "b" onclick = " javascript : clicked () " value = "click me b" />
<script type = "text/javascript" >
function clicked () {
console . log ( this . value );
}
</script>
來看瀏覽器幫我們做瞭什麼: onclick="[js code]"
瀏覽器會幫我們生成(這點我不確定,但按這種方式理解可以行得通)
[dom].onclick = function() {[js code]}
好,看看上面兩個都發生瞭什麼:
        <script type = "text/javascript" >
// a
document . getElementById ( "a" ). onclick = function () {
console . log ( this . value );
}
// b
document . getElementById ( "b" ). onclick = function () {
clicked ();
}
</script>
        解釋清楚瞭吧。還是owner變 瞭

3. 瀏覽器行為
這一點我隻是順便看到說ie和ff在綁定事件上的區別(attachEvent、addEventListener)繼續看例子:
        c: <input type = "button" id = "c" value = "click me c" />
<script type = "text/javascript" >
var c = document . getElementById ( "c" );
if ( document . attachEvent ) {     // for ie
c . attachEvent ( 'onclick' , clicked );
} else {
c . addEventListener ( 'click' , clicked , false );
}
</script>
       ie下輸出undefined, ff下輸出click me c, why? 加點debug信息再看看
        d: <input type = "button" id = "d" value = "click me d" />
<script type = "text/javascript" >
function clicked2 () {
console . log ( this , arguments );
for ( var i = 0 ; i != arguments . length ; ++ i ) {
console . log ( 'arg' , i , ':' , arguments [ i ]);
}
}
var d = document . getElementById ( "d" );
if ( document . attachEvent ) {     // for ie
d . attachEvent ( 'onclick' , clicked2 );
} else {
d . addEventListener ( 'click' , clicked2 , false );
}
</script>
        看到瞭吧,ie下this成瞭window,ff則是出發時間的dom。不過兩個都會給clicked2傳個參數event  

摘自 懶人小何

發佈留言