哈Ha! 我向您介绍
Cristi Salcescu撰写的文章
“当这种“失去语境”时该怎么办”的
译文 。
避免丢失
此上下文的最佳方法是不使用
this 。 但是,这并不总是可能的。 例如,我们与使用
此代码的其他人的代码或库一起工作。
原型系统中的对象文字,构造函数,类对象构造函数。 在原型系统中使用此伪
参数以便访问对象的属性。
让我们看一些情况。
嵌套函数
这会丢失嵌套函数内部的上下文引用。
class Service { constructor(){ this.numbers = [1,2,3]; this.token = "token"; } doSomething(){ setTimeout(function doAnotherThing(){ this.numbers.forEach(function log(number){
doSomething()方法
具有两个嵌套函数:
doAnotherthing()和
log() 。 当调用
service.doSomething()时 ,
这会丢失嵌套函数中的上下文引用。
绑定()
解决问题的一种方法是使用
bind()方法。 看下面的代码:
doSomething(){ setTimeout(function doAnotherThing(){ this.numbers.forEach(function log(number){ console.log(number); console.log(this.token); }.bind(this)); }.bind(this), 100); }
bind()创建函数的新版本,该函数在调用时已经具有
this的某个值。
函数doAnotherThing(){/*...*/}.bind(this)创建
doAnotherThing()函数的版本,该函数从
doSomething()中获取此值。
那/自我
另一个选择是声明并使用新的
that / self变量,该变量将存储
doSomething()方法中的
this值。
doSomething(){ let that = this; setTimeout(function doAnotherThing(){ that.numbers.forEach(function log(number){ console.log(number); console.log(that.token); }); }, 100); }
我们必须在嵌套函数中使用
this的所有方法中声明
let that = this 。
箭头功能
箭头功能为我们提供了解决此问题的另一种方法。
doSomething(){ setTimeout(() => { this.numbers.forEach(number => { console.log(number); console.log(this.token); }); }, 100); }
箭头函数不会
为此创建自己的上下文,而是使用周围上下文的
this值。 在上面的示例中,它使用父函数的
this的值。
该方法的缺点是我们无法指定箭头函数的名称。 函数的名称起着重要的作用,因为它增加了代码的可读性并描述了其目的。
下面是相同的代码,但函数以变量名表示:
doSomething(){ let log = number => { console.log(number); console.log(this.token); } let doAnotherThing = () => { this.numbers.forEach(log); } setTimeout(doAnotherThing, 100); }
回调函数(方法作为回调)
将方法用作回调函数时,
这会丢失上下文引用。 让我们看下面的类:
class Service { constructor(){ this.token = "token"; } doSomething(){ console.log(this.token);
让我们看一下其中
service.doSomething()方法用作回调函数的情况。
在上述所有情况下,
这都会丢失上下文链接。
绑定()
我们可以使用
bind()解决此问题。 以下是此选项的代码:
箭头功能
另一种方法是创建一个调用
service.doSomething()的箭头函数。
反应组件
在组件中,当方法用作事件的回调时,
这会丢失上下文引用。
class TodoAddForm extends React.Component { constructor(){ super(); this.todos = []; } componentWillMount() { this.setState({desc: ""}); } add(){ let todo = {desc: this.state.desc};
作为解决方案,我们可以在将使用
bind(this)的构造函数中创建新函数。
constructor(){ super(); this.todos = []; this.handleChange = this.handleChange.bind(this); this.add = this.add.bind(this); }
不要使用“ this”
不,
这 -没有上下文丢失的问题。 可以使用
工厂函数创建对象。 看一下这个例子:
function Service() { let numbers = [1,2,3]; let token = "token"; function doSomething(){ setTimeout(function doAnotherThing(){ numbers.forEach(function log(number){ console.log(number); console.log(token); }); }, 100); } return Object.freeze({ doSomething }); }
如果将该方法用作回调,则上下文仍然保留。
let service = Service(); service.doSomething();
结论
这在各种情况下都会丢失上下文引用。
bind() ,使用
那个/自变量和箭头函数是解决上下文问题的方法。
使用工厂函数可以创建不使用
this的对象。