閱讀437 返回首頁    go 阿裏雲 go 技術社區[雲棲]


Javascript編程“陷阱”總結

關於this關鍵字

首先看一段代碼:

var obj = {
    id: "xyz",
    printId: function() {
        console.log('The id is '+ this.id + ' '+ this.toString());
    }
};
obj.printId();   //The id is xyz [object Object]
var callback=obj.printId;
callback();   //The id is undefined [object global]
setTimeout(obj.printId,1000);   //The id is undefined [object Object]

這樣就出現問題了,隻有obj.printId()返回了我們想要的結果,第二種調用隻是個賦值,但this卻指向global,第三種調用,this指向Object,但是顯然不是我們定義的obj,因此它獲取不到id屬性。原因就在於,在javascript中,this關鍵字的指向是在函數調用的時候定義的。callback()在調用的時候,屬於全局頂層的函數,已經不是我們定義的obj中的一個函數,所以this指向global,至於setTimeout的回調函數調用方式之所以指向一個Object,這應該和setTimeout這個api的實現方式有關

那我們有沒有辦法用callback和setTimeout方式顯示出正常結果呢?你可以這樣寫:

obj.printId();   //The id is xyz [object Object]
var callback=function() { obj.printId(); };
callback();   //The id is xyz [object Object]
setTimeout(function() {obj.printId(); },1000);   //The id is xyz [object Object]

關於變量作用域

第一個,最簡單的例子:

for(var i = 0; i < 5; i++) {
  console.log(i);   //0 1 2 3 4
}

第二個,加個異步函數,也很簡單:

for(var i = 0; i < 5; i++) {
    setTimeout(function() {
        console.log(i);   //5 5 5 5 5
    }, 100);
}

第三個,我們製作一個方法數組:

var data = [];
for (var i = 0; i < 5; i++) {
    data[i] = function foo() {
        console.log(i);
    };
}
data[0](); data[1](); data[2](); data[3](); data[4]();   //5 5 5 5 5

第一個,如我們所想,輸出0,1,2,3,4;可是第二個第三個都是5,5,5,5,5.

原因分析:我們在for循環中定義的變量i,在for循環結束後還沒有走出它的作用域,也就是說for循環之後,i依然可以訪問,值等於最後一次循環後的值,就是5了。第二段代碼中,setTimeout的回調函數執行時,for循環已經完成,此時i就是5。同理,第三段代碼,在datai執行時,i已經是5了。當然,我們有辦法讓它顯示正確結果,但要增加一個變量,像這樣:

for(var i = 0; i < 5; i++) {
    (function() {
        var j = i;
        setTimeout( function() { console.log(j); }, 500*i);   //0 1 2 3 4
    })();
}

bonus:在object外麵增加method的方法

var obj1 = { id: "Foo"};
var obj2 = { id: "Bar"};
function f1(a, b) {
    console.log(this, a, b);
}
f1.call(obj1, 'A', 'B'); //Object{id:"Foo"} "A" "B"
f1.apply(obj2, [ 'A', 'B' ]); //Object{id:"Bar"} "A" "B"

最後更新:2017-06-23 23:35:15

  上一篇:go  《深入理解Elasticsearch(原書第2版)》一2.2.1 前綴查詢示例
  下一篇:go  《深入理解Elasticsearch(原書第2版)》一2.2 查詢改寫