2014-02-26 88 views
0

我一直在做一些使用Javascript回調的玩法,並瞭解圍繞「this」的範圍問題以及如何通過使用「call」或「apply」並傳入對象引用來消除它。Javascript - 「this」範圍問題修復

但是,我發現了一些東西,我想知道以下是否是不好的做法?因爲它通過純粹使用對象名稱而不是「this」來消除範圍問題。說我有其中有一個回調,例如,功能:

function getUserInput(firstName, lastName, callback) { 
    callback(firstName, lastName); 
} 

而且這樣的對象:

var clientData = { 
    id: 1, 
    fullName: "Not Set", 
    setUserName: function (firstName, lastName) { 
    //this.fullName = firstName + " " + lastName; 
    clientData.fullName = firstName + " " + lastName; 
    } 
} 

要執行並查看代碼的輸出I做到以下幾點:

getUserInput("Ann", "Other", clientData.setUserName); 

console.log(clientData.fullName); 

哪給了我「安其他」。完善!而如果我取消註釋「this.fullName」行並註釋掉「clientData.fullName」,我會得到「未設置」,並且window.fullName將包含「Ann Other」(傳統範圍問題「this」附加到全局窗口)。

當然,這是一個原始的例子,但這是不好的做法?現在它意味着我從來沒有在回調函數中訪問本地屬性的問題。我也不需要使用「調用」或「應用」函數並傳入對象引用,以便我可以在正確的範圍內訪問「this.propertyName」。任何答案將不勝感激。

回答

3

是的,這是一種不好的做法。鑑於支持,使用Function.prototype.bind

getUserInput("Ann", "Other", clientData.setUserName.bind(clientData)); 

(這是不太多餘的,當你有一個原型關的工作。)

或者,萬無一失的但不那麼漂亮的解決方案:

getUserInput("Ann", "Other", function(firstName, lastName) { 
    clientData.setUserName(firstName, lastName); 
}); 

獎金ES6模式(但如果你有ES6,你爲什麼不使用bind?)

getUserInput("Ann", "Other", (...args) => clientData.setUserName(...args)); 
0

在其方法中引用對象的名稱絕對不是一種好的做法,因爲如果更改對象的名稱,則應更改該方法的實現。

我會建議你使用:

getUserInput("Ann", "Other", clientData.setUserName.bind(clientData)); 

console.log(clientData.fullName); 

問題是因爲你調用回調callback(firstName, lastName);沒有.操作,這與關聯特定上下文的方法調用。

bind是ES5的一部分,如果你正在尋找更廣泛的瀏覽器兼容性,您可以:

getUserInput("Ann", "Other", function (data) { 
    clientData.setUserName.apply(clientData, arguments); 
}); 

console.log(clientData.fullName); 
+1

的「數據」參數是不是真的需要,雖然肯定?由於參數參數爲setUserName函數提供了值? – user2241336

+0

是的,我喜歡綁定方法,它是有道理的。我只是好奇,因爲我偶然發現的工作非常好,並且明白如果方法名稱發生變化,我將不得不重新命名(在某些方面,這是一個不太可能的但容易的改變)。 我也很感激我可以使用「應用」或「調用」並傳入上下文對象。 還有另一種方式訪問​​屬性,並避免設置屬性「self = this;」的範圍問題。然後通過object.self.propertyName訪問屬性。我只是好奇,因爲它被認爲是好的和壞的實踐,因爲它可能是一個非常被誤解的領域。 – user2241336