P粉9211300672023-08-21 14:13:52
bind()
函數。 bind()
函數function MyConstructor(data, transport) {
this.data = data;
transport.on('data', ( function () {
alert(this.data);
}).bind(this) );
}
// 模拟传输对象
var transport = {
on: function(event, callback) {
setTimeout(callback, 1000);
}
};
// 调用方式
var obj = new MyConstructor('foo', transport);
如果您使用Underscore.js - http://underscorejs.org/#bind
#transport.on('data', _.bind(function () { alert(this.data); }, this));
function MyConstructor(data, transport) {
var self = this;
this.data = data;
transport.on('data', function() {
alert(self.data);
});
}
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', () => {
alert(this.data);
});
}
P粉1761515892023-08-21 10:04:21
this
的知識this
(也稱為「上下文」)是每個函數內部的特殊關鍵字,其值只取決於函數的呼叫方式,而不是定義方式。它不受詞法作用域的影響,與其他變數不同(除了箭頭函數,見下文)。以下是一些範例:
function foo() { console.log(this); } // 普通函数调用 foo(); // `this` 将引用 `window` // 作为对象方法 var obj = {bar: foo}; obj.bar(); // `this` 将引用 `obj` // 作为构造函数 new foo(); // `this` 将引用从 `foo.prototype` 继承的对象
要了解更多關於 this
的知識,請參閱MDN文件。
this
#ECMAScript 6 引入了箭頭函數,可以將其視為lambda函數。它們沒有自己的this
綁定。相反,this
在作用域中查找,就像普通變數一樣。這意味著你不需要呼叫.bind
。它們還具有其他特殊行為,請參閱MDN文件以了解更多資訊。
function MyConstructor(data, transport) { this.data = data; transport.on('data', () => alert(this.data)); }
this
#實際上,你不需要特別訪問this
,而是需要存取它所指的物件。因此,一個簡單的解決方案是建立一個新變量,也指向該物件。變數可以有任何名稱,但常見的是self
和that
。
function MyConstructor(data, transport) { this.data = data; var self = this; transport.on('data', function() { alert(self.data); }); }
由於self
是一個普通變量,它遵循詞法作用域規則,並且可以在回調函數內部存取。這還有一個優點,就是可以存取回呼函數本身的this
值。
this
- 第一部分看起來你無法控制this
的值,因為它的值是自動設定的,但實際上並非如此。
每個函數都有一個方法.bind
[文件],它會傳回一個會this
綁定到一個值的新函數。該函數的行為與你呼叫.bind
時的函數完全相同,只是this
由你設定。無論如何或何時呼叫該函數,this
將始終引用傳遞的值。
function MyConstructor(data, transport) { this.data = data; var boundFunction = (function() { // 括号不是必需的 alert(this.data); // 但可能提高可读性 }).bind(this); // <- 这里我们调用了`.bind()` transport.on('data', boundFunction); }
在這種情況下,我們將回呼函數的this
綁定到MyConstructor
的this
值。
注意:對於jQuery的綁定上下文,使用jQuery.proxy
[文件]。這樣做的原因是在解綁事件回呼時不需要儲存函數的參考。 jQuery在內部處理這個。
this
- 第二部分一些接受回呼函數的函數/方法也接受一個值,該值應該作為回呼函數的this
。這與手動綁定相同,但是函數/方法會為你執行綁定。例如,Array#map
[文檔]就是這樣的方法。它的簽名是:
array.map(callback[, thisArg])
第一個參數是回呼函數,第二個參數是this
應該要引用的值。以下是一個人為的範例:
var arr = [1, 2, 3]; var obj = {multiplier: 42}; var new_arr = arr.map(function(v) { return v * this.multiplier; }, obj); // <- 这里我们将`obj`作为第二个参数传递
注意:是否可以傳遞this
的值通常在函數/方法的文件中提到。例如,jQuery的$.ajax
方法[文件]描述了一個名為context
的選項:
這個問題的另一個常見表現形式是將物件方法用作回調/事件處理程序。在JavaScript中,函數是一等公民,術語「方法」只是指一個作為物件屬性值的函數。但是該函數與其「包含」物件之間沒有特定的連結。
考慮以下範例:
function Foo() { this.data = 42, document.body.onclick = this.method; } Foo.prototype.method = function() { console.log(this.data); };
函數this.method
被指派為點擊事件處理程序,但如果點擊document.body
,記錄的值將是undefined
,因為在事件處理程序內部,this
指的是document.body
,而不是Foo
的實例。
如前所述,this
引用的是函數如何呼叫,而不是如何定義。
如果程式碼如下所示,可能更明顯函數沒有隱式引用物件:
function method() { console.log(this.data); } function Foo() { this.data = 42, document.body.onclick = this.method; } Foo.prototype.method = method;
解決方案與上面提到的相同:如果可用,使用.bind
將this
明確綁定到特定值
document.body.onclick = this.method.bind(this);
或透過使用匿名函數作為回調/事件