ES6类的范围

布伦丹·奎因(Brendan Quinn)

我了解以下代码段中发生了什么,以及如何解决(通过绑定或通过将构造结构外部的walkfriend成为方法)来解决,但是为什么会发生这种情况?在我看来,必须将类的范围绑定到其自己的方法上是违反直觉的。

class Person {
    constructor(name, friend) {
        this._name = name;
        if(friend) {
          this.walkFriend = friend.walk;
        }
    }
  
    get name() {
        return this._name.toUpperCase();
    }
  
    walk() {
        console.log(this.name + ' is walking.');
    }
}
         
let bob = new Person('Bob');
let bill = new Person('Bill', bob);

console.log(bob.name); // BOB
console.log(bill.name); // BILL
bill.walk() // Bill is walking.
bill.walkFriend(); // We expect 'BOB is walking', but we get 'BILL is walking.'

TJ人群

发生的是,ES2015(“ ES6”)类中的“方法”与实例之间没有内在联系,就像没有使用较早的样式构造函数friend.walk一样。¹仅返回原始方法引用,没有任何内容关于它的约束,friend除非您自己这样做。换句话说,friend.walk === Person.prototype.walktrue例如,您的违反直觉的理解是正确的(除非它与范围无关,而与的价值有关this)。:-)

请记住,新class东西几乎完全是语法糖(但是,您知道,这是好糖)。您的Person课程几乎完全等同于以下ES5代码:

var Person = function Person(name, friend) {
    this._name = name;
    if(friend) {
        this.walkFriend = friend.walk;
    }
};

Object.defineProperty(Person.prototype, "name", {
    get: function() {
        return this._name.toUpperCase();
    },
    configurable: true
});

Object.defineProperty(Person.prototype, "walk", {
    value: function() {
        console.log(this.name + ' is walking.');
    },
    writable: true,
    configurable: true
});

您已经说过您知道如何解决这个问题,并且实际上两种解决方案都可以工作,只要绑定即可:

constructor(name, friend) {
    this._name = name;
    if(friend) {
        this.walkFriend = friend.walk.bind(frield);   // **
    }
}

walk在构造函数中创建为箭头函数,而不是在原型上创建:

constructor(name, friend) {
    this._name = name;
    this.walk = () => {                           // **
        console.log(this.name + ' is walking.');  // **
    };                                            // **
    if(friend) {
        this.walkFriend = friend.walk;
    }
}

¹有方法和之间内在的联系原型它中定义的类,如果使用,将使用该super方法中的关键字。规范调用链接了方法的[[HomeObject]]字段(但是您无法在代码中访问它,如果您不使用super该方法,则可以由JavaScript引擎对其进行优化)。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章