Класс JS: разница между ES6 myFunc(){..} и ES5 myFunc = function() {} в объявлении класса

В следующем коде

class PersonClass {
  constructor(fname) {
    this.fname = fname;
  }
  read = function() { console.log('I am reading') }
  speak () { console.log('I am speaking'); }
}

//Instantiate 
let p1 = new PersonClass('Raj')

read = function() { console.log('I am reading') } становится свойством вновь созданного экземпляра, т.е.

p1.hasOwnProperty('read') is true

вместо speak() { console.log('I am speaking'); } назначается PersonClass.prototype. то есть

p1.hasOwnProperty('speak') is False

p1.__proto__.hasOwnProperty('speak') is true

Может кто-нибудь объяснить, почему это происходит.

По сути, в чем разница между двумя способами объявления методов внутри класса.

Я думал, что speak() {...} — это просто более короткий синтаксис для speak = function() {...} (в ES6).

Спасибо


person appu    schedule 26.07.2019    source источник
comment
потому что js следует прототипному наследованию.   -  person Jai    schedule 26.07.2019
comment
Нет, синтаксис метода не является аббревиатурой свойств класса.   -  person Bergi    schedule 26.07.2019
comment
Синтаксис variableName = ... в теле класса эквивалентен оператору this.variableName = ... в constructor.   -  person Titus    schedule 26.07.2019


Ответы (1)


read = function() { console.log('I am reading') }

— это новый синтаксис поля класса. Фактически это то же самое, что и присваивание свойству read экземпляра внутри конструктора:

class PersonClass {
  constructor(fname) {
    this.read = function() {
      console.log('I am reading')
    }
    this.fname = fname;
  }
  speak() {
    console.log('I am speaking');
  }
}

speak, с другой стороны, является обычным методом класса, что означает, что он находится в прототипе, PersonClass.prototype, что то же самое, что и Object.getPrototypeOf(p1), что то же самое, что и p1.__proto__ (устаревший синтаксис).

class PersonClass {
  constructor(fname) {
    this.read = function() {
      console.log('I am reading')
    }
    this.fname = fname;
  }
  speak() {
    console.log('I am speaking');
  }
}
let p1 = new PersonClass('Raj')
console.log(
  PersonClass.prototype.hasOwnProperty('speak'),
  Object.getPrototypeOf(p1) === PersonClass.prototype,
  p1.__proto__ === PersonClass.prototype
);

Таким образом, свойство speak относится к внутреннему прототипу экземпляра, а не к самому экземпляру. Свойство read является прямым свойством экземпляра, как и свойство fname.

Имейте в виду, что синтаксис поля класса все еще является экспериментальным предложением (этап 3). По крайней мере, это реализовано в Chrome, но пока не совсем официально.

person CertainPerformance    schedule 26.07.2019
comment
Возможно, вы захотите упомянуть, что свойства класса по-прежнему являются только предложением. - person Bergi; 26.07.2019