在javascript中,实例函数和Function类型的实例变量有什么区别?

In javascript, what's the difference between an instance function and instance variable of type Function?

我知道区别之一是函数类型的实例变量自动绑定到 class。例如:

class Dog {
  sound = 'woof'
  bark() {
    console.log(this)
  }
  boundBark = () => {
    console.log(this)
  }
}

const fido = new Dog()
fido.bark() // woof
fido.boundBark() // woof
const bark = fido.bark
bark() // undefined
const boundBark = fido.boundBark
boundBark() // woof

Dog { sound: 'woof', boundBark: [Function: boundBark] }
Dog { sound: 'woof', boundBark: [Function: boundBark] }
undefined
Dog { sound: 'woof', boundBark: [Function: boundBark] }

为什么会这样,这两种编写实例函数的方式之间还有其他区别吗?

您可以检查这些方式对 Dog.prototype 对象的作用:

方法定义:

class Dog {
  bark() {
    console.log(this) // *this* referss to the actual instance
  }
}

console.log(Dog.prototype.bark); // function bark

Public class field [MDN]:

class Dog {
  bark = () => {
    console.log(this); // also, *this* refers to the actual instance
  }
}

console.log(Dog.prototype.bark); // undefined

在第一种情况下,您在 class 原型中定义了一个函数,而在后者中,您在“构造函数时”在实例中定义了变量,对于任何其他变量也是如此。

后者与做的一样:

class Dog {
  constructor() {
    
    this.bark = () => {
      // this is the reason why *this* is actually available
      // and refers to the actual instance
      console.log(this);
    }
    
    /* The rest of defined constructor */
  }
}

console.log(Dog.prototype.bark); // undefined

请记住Public class fieldECMAs标准中还没有引入,所以很多JS环境无法支持它们,你应该使用一些工具如Babel来实现向后兼容。由于这个原因,一些行为仍然依赖于应用程序(比如定义优先级)。