【发布时间】:2020-07-03 22:23:21
【问题描述】:
美好的一天
我最近遇到了一个奇怪的情况,我的 this 在类的成员函数中的值未定义。我知道有很多与未定义的this 上下文相关的问题,但我找不到这个问题的任何解释。我很想知道为什么会这样。在这个例子中,为什么setModified函数的箭头函数实现保留了它的this上下文,而类上的函数却没有。
这个例子打破了块类的setModified函数
class point {
constructor(x, y) {
this._x = x || 0;
this._changeEvents = [];
}
set changeEvent(eventFunction) {
this._changeEvents.push(eventFunction);
}
set x(value) {
this._x = value;
this.runChangeEvent();
}
set y(value) {
this._y = value;
this.runChangeEvent();
}
get x() {
return this._x;
}
get y() {
return this._y;
}
runChangeEvent() {
this._changeEvents.forEach(event => event(this));
}
}
class renderItem {
constructor(canvas) {
this._canvas = canvas;
}
render(){
}
}
class block extends renderItem {
constructor(canvas) {
super(canvas);
this._modified = true;
this._topLeft = new point(0, 0);
this._topLeft.changeEvent = this.setModified;
}
//Using a method on the class as a callback, it breaks
setModified(){
this._modified = true;//breaks, this is undefined
console.log(this);
}
//Sets
set topLeft(value) { this._topLeft = value; }
//Gets
get topLeft() { return this._topLeft }
}
//Creates an instance of the block
const bl = new block(null);
bl.topLeft.x = 20;
但是当您将setModified 函数更改为箭头函数(也在类上)时,它可以工作:
class point {
constructor(x, y) {
this._x = x || 0;
this._y = y || 0;
this._changeEvents = [];
}
set changeEvent(eventFunction) {
this._changeEvents.push(eventFunction);
}
set x(value) {
this._x = value;
this.runChangeEvent();
}
set y(value) {
this._y = value;
this.runChangeEvent();
}
get x() {
return this._x;
}
get y() {
return this._y;
}
runChangeEvent() {
this._changeEvents.forEach(event => event(this));
}
}
class renderItem {
constructor(canvas) {
this._canvas = canvas;
}
render(){
}
}
class block extends renderItem {
constructor(canvas) {
super(canvas);
this._modified = true;
//Using an arrow function on the class instance as a callback, it works
this.setModified = () => {
this._modified = true;//works
console.log(this);
};
this._topLeft = new point(0, 0);
this._topLeft.changeEvent = this.setModified;
}
//Sets
set topLeft(value) { this._topLeft = value; }
//Gets
get topLeft() { return this._topLeft }
}
const bl = new block(null);
bl.topLeft.x = 20;
为什么类上的成员函数会丢失 this 上下文而不是箭头函数?
【问题讨论】:
-
this._topLeft.changeEvent = this.setModified;setModified 正在转移到另一个变量,该变量没有另一个变量作为属性。this._modified存在。this._topLeft._modified没有 -
注意这里有很多与具体问题无关的代码。将来,如果您将其缩小到 minimal reproducible example 并删除任何不相关的内容,将会有所帮助
-
在@Taplar的评论中添加,重新分配时可以拨打
bind(this),防止丢失this。this._topLeft.changeEvent = this.setModified.bind(this); -
哦...所以范围从块类变为点类,因为现在它是点类上的成员函数。我从来没有这样想过。因此,该函数现在将具有两个作用域或闭包,具体取决于调用它的位置。如果我理解正确?
-
我重新创建了问题。
this不绑定到this._topLeft。实际上是undefined。从我在回答中引用的书中,在试图理解为什么会发生默认绑定之后:var bar = obj.foo;然后调用bar()即使bar似乎是对obj.foo的引用,实际上,它实际上只是另一个引用到foo自己。此外,调用点很重要,调用点是bar(),这是一个普通的、未修饰的调用,因此适用默认绑定。我更新了我的答案,如果我说错了,请告诉我。
标签: javascript ecmascript-6 scope