JavaScript匿名函数this丢失原因及.bind(this)修复原理咨询
你遇到的这个问题是JavaScript里this绑定规则的经典坑,完全不是你的理解有问题——咱们一步步拆解清楚:
首先先把你的代码格式化一下,看起来更直观:
const team = { members: ['Tony', 'Peter'], teamName: 'Avengers', teamSummary: function() { return this.members.map(function(member) { return `${member} is a member of ${this.teamName}`; }); } }; team.teamSummary();
为什么会出现TypeError?
你的直觉没错:当调用team.teamSummary()时,teamSummary函数内部的this确实指向team对象,这部分完全正确。
问题出在map方法里的匿名回调函数上!JavaScript中,普通函数(非箭头函数)的this指向是由它的调用方式决定的,而不是它定义的位置。这里的匿名函数是被map方法调用的,而map默认不会给回调函数绑定外部的this——在非严格模式下,这个匿名函数的this会指向全局对象(浏览器里是window,Node.js里是global);严格模式下则直接是undefined,这就导致了Cannot read property 'teamName' of undefined的错误。
.bind(this)是怎么解决问题的?
Function.prototype.bind()的作用是创建一个新的函数副本,并且把这个新函数的this永久绑定到你传入的参数上——不管后续这个函数被怎么调用,它的this都不会变。
在你的代码里,给map的回调函数加上.bind(this)后,这里的this是teamSummary函数内部的this(也就是team对象),所以绑定后的匿名函数里的this就固定指向team了,自然就能正常访问team.teamName。
修改后的代码如下:
const team = { members: ['Tony', 'Peter'], teamName: 'Avengers', teamSummary: function() { return this.members.map(function(member) { return `${member} is a member of ${this.teamName}`; }.bind(this)); // 绑定外部的this到回调函数 } }; team.teamSummary(); // 返回 ["Tony is a member of Avengers", "Peter is a member of Avengers"]
额外补充两种更常用的解决方案
除了.bind(this),还有两种更简洁的方式可以解决这个问题:
1. 用变量保存外部的this
在teamSummary函数内部,把this赋值给一个变量(比如self或者that),然后在回调函数里用这个变量代替this:
const team = { members: ['Tony', 'Peter'], teamName: 'Avengers', teamSummary: function() { const self = this; // 保存外部的this return this.members.map(function(member) { return `${member} is a member of ${self.teamName}`; }); } };
2. 使用ES6箭头函数(最推荐)
箭头函数不会绑定自己的this,它会继承外层作用域的this,所以直接用箭头函数作为map的回调,就能自动获取teamSummary里的this:
const team = { members: ['Tony', 'Peter'], teamName: 'Avengers', teamSummary: function() { return this.members.map(member => { return `${member} is a member of ${this.teamName}`; }); } };
内容的提问来源于stack exchange,提问作者Bikal Nepal

