JavaScript回调函数执行时this指向错误,如何让其指向原对象?
如何确保回调函数中的this指向目标对象?
问题场景
我编写了如下JavaScript代码:
function A() { this.name = 'John'; } A.prototype.getName = function() { return this.name; } function B() { } B.prototype.callApi = function(cb) { var context = arguments[0]; // 这里注意:arguments[0]就是传入的cb,这行代码其实没起到作用 setTimeout(function() { console.log('server data combine with ' + cb()); }, 1000); } var a = new A(); console.log(a.getName()); // 这里输出"John",正常 var b = new B(); b.callApi(a.getName); // 这里执行cb时,this没有指向a,输出undefined或全局相关值
我希望执行getName函数时,this变量指向a对象,但当前执行回调函数cb时,this并未指向a对象,请问该如何解决?
问题原因
当你把a.getName作为参数传递给callApi时,你传递的只是这个函数的引用,它和原对象a的绑定关系被切断了。当setTimeout触发调用这个函数时,它是作为普通函数执行的,此时this的指向取决于执行环境:非严格模式下指向全局对象,严格模式下则为undefined,自然无法获取到a.name。
解决方案
这里有几种常用的方法来固定this的指向:
1. 使用Function.prototype.bind()绑定上下文
bind()方法会创建一个新函数,这个新函数无论何时被调用,它的this都会指向你指定的对象。修改调用callApi的代码即可:
b.callApi(a.getName.bind(a));
这样传递给callApi的是一个已经绑定了a作为this的新函数,执行时就能正确获取到this.name。
2. 使用箭头函数作为包装器
箭头函数的this是继承自外层作用域的,所以我们可以用箭头函数包裹对a.getName()的调用,确保调用时的上下文正确:
b.callApi(() => a.getName());
这里箭头函数本身的this不影响,我们直接通过变量a调用它的方法,自然能拿到正确的name值。
3. 在callApi内部手动指定上下文(可选优化)
如果你有权修改B.prototype.callApi的代码,也可以在调用cb时用call或apply手动指定上下文。不过首先你需要修正原代码里的context赋值错误(原代码把cb赋值给了context),比如可以让callApi接收一个上下文参数:
B.prototype.callApi = function(cb, context) { setTimeout(function() { console.log('server data combine with ' + cb.call(context)); }, 1000); } // 调用时传入上下文a b.callApi(a.getName, a);
这种方式更灵活,适合需要动态指定上下文的场景。
内容的提问来源于stack exchange,提问作者Will
相关产品推荐
相关产品推荐

