维护对“this”的引用在Javascript中使用回调和闭包时
Maintaining the reference to "this" in Javascript when using callbacks and closures
我发现自己将"this"赋值给一个变量,这样我就可以很容易地在回调和闭包中使用它。
这种做法不好吗?是否有更好的方法返回到原始函数?
下面是一个典型的例子。
User.prototype.edit = function(req, res) {
var self = this,
db = this.app.db;
db.User.findById('ABCD', function(err, user)) {
// I cannot use this.foo(user)
self.foo(user);
});
};
User.prototype.foo = function(user) {
};
你通常使用这种方法还是你找到了一个更干净的解决方案?
有三种主要的方法来处理回调中的this
:
1。创建一个词法作用域变量,就像您当前所做的那样
这个新变量最常用的两个名称是that
和self
。我个人更喜欢使用that
,因为浏览器有一个全局窗口属性称为self和我的过滤器抱怨,如果我阴影它。
function edit(req, res) {
var that = this,
db.User.findById('ABCD', function(err, user){
that.foo(user);
});
};
这种方法的一个优点是,一旦代码转换为使用that
,您可以添加尽可能多的内部回调,并且由于词法作用域,它们都将无缝地工作。另一个优点是它非常简单,即使在旧的浏览器上也能工作。
2。使用.bind()方法
Javascript函数有一个.bind()
方法,可以让你创建一个具有固定this
的版本。
function edit(req, res) {
db.User.findById('ABCD', (function(err, user){
this.foo(user);
}).bind(this));
};
当涉及到处理this
时,bind方法对于必须添加包装函数的回调之一特别有用:
setTimeout(this.someMethod.bind(this), 500);
var that = this;
setTimeout(function(){ that.doSomething() }, 500);
bind
的主要缺点是,如果你有嵌套回调,那么你还需要对它们调用bind
。另外,IE <= 8和其他一些老浏览器,并没有本地实现bind
方法,所以如果你仍然需要支持它们,你可能需要使用某种shimming库。
3。如果您需要对函数范围或参数进行更细粒度的控制,请退回到.call()和.apply()
在Javascript中控制函数参数的更原始的方法,包括this
,是.call()
和.apply()
方法。它们允许您以任意对象作为其this
并以任意值作为其参数来调用函数。apply
对于实现可变函数特别有用,因为它接收参数列表作为数组。
例如,下面是bind的一个版本,它以字符串形式接收要绑定的方法。这让我们只写一次this
,而不是两次。
function myBind(obj, funcname){
return function(/**/){
return obj[funcname].apply(obj, arguments);
};
}
setTimeout(myBind(this, 'someMethod'), 500);
尽管that
是this
"copy"的广泛命名约定,但不幸的是,这是一种行之有效的方法。
你也可以试试:
db.User.findById('ABCD', this.foo.bind(this));
但是这种方法要求foo()
具有与findById()
所期望的完全相同的签名(在您的示例中,您跳过了err
)。
您可以为回调创建一个代理:
var createProxy = function(fn, scope) {
return function () {
return fn.apply(scope, arguments);
};
};
使用它,您可以做以下操作:
db.User.findById('ABCD', createProxy(function(err, user)) {
this.foo(user);
}, this));
jQuery做了类似的事情:$.proxy
并且,正如其他人在使用bind
时注意到的那样,如果兼容性存在问题,请查看此处:
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind兼容性
- javascript,将参数传递给函数内部的闭包中的回调
- JavaScript闭包&回调函数
- 使用闭包/函数绑定将自函数作为回调传递
- 使用JavaScript回调函数了解变量作用域和闭包
- 带有 Javascript 回调的闭包
- 非常基本的JavaScript回调/闭包结构
- 闭包的意外行为:回调保存最后一个值
- 尝试使用带有参数的闭包作为回调
- 对闭包变量的更改是否在使用闭包的回调中可见
- 创建带有回调的动态 JSON 数组(内部闭包问题)
- JSONP 回调和闭包/范围
- Is回调函数始终是一个闭包
- Javascript闭包:Phonegap和'这'在回调中
- 参数对应关系:回调与闭包(?)
- 回调中的闭包
- 我需要在DOM事件回调中使用闭包吗
- 使用Google闭包编译器记录回调参数
- 访问子元素内的父作用域's onclick回调(Atom包)
- 维护对“this”的引用在Javascript中使用回调和闭包时
- javascript回调闭包未定义变量