2016-06-22 8 views
1
class a { 
    get b() { 
     delete this.b; 
     return this.b = 1; 
    } 
} 

var c = { 
    get b() { 
     delete this.b; 
     return this.b = 1; 
    } 
} 

console.log(c.b); // works as expected 
console.log((new a()).b); // throws error 

Приведенный выше код должен работать нормально, но последняя строка выбрасывается.Ленивый геттер не работает в классах

Uncaught TypeError: Cannot set property b of # which has only a getter(…)

Очевидно, что геттер не удаляется в классе, тогда как он отлично работает в объекте. Я нахожусь на последнем стабильном хроме.

Lazy Getter MDN Entry

+0

Вы не конструктор в классе 'a' – Redu

+0

@Redu Конструктор является необязательным в Js классов. – Achshar

+0

Я не мог найти ссылку после достаточного количества поисковых запросов, поэтому я делаю это комментарием вместо ответа, но я на 95% уверен, что методы в классах становятся неконфигурируемыми и, следовательно, удаляются сбой , Вы можете имитировать это поведение в «обычных» классах. –

ответ

5

Поглотитель класса сидит на .prototype объекта, а не на this, поэтому ваша попытка delete это не удается (и, как Джереми указывает, что это не файл удаляемый).

Однако вы можете просто создать собственное свойство на экземпляре, что тень сорбента:

class a { 
    get b() { 
     Object.defineProperty(this, "b", { value: 1, writable: false, configurable: true }) 
     return this.b; 
    } 
} 

var c = new a; 
console.log(c.b); // 1 

Мы должны использовать Object.defineProperty() в качестве простого присваивания бы найти наследственное имущество, которое не имеет сеттера и броски.

+1

Ох ... затенение геттера - эта идея никогда не приходила мне в голову. Это круто. –

+0

Вы просто создаете свойство 'b'' a', я не думаю, что вам нужна вся эта церемония. Просто сделайте 'get b() {return this.b} set b (v) {this.b = v}', и все в порядке. – Redu

+0

@Redu: Это бесконечная рекурсия? – Bergi

0

Конструктивно, свойства класса не файл удаляемый - ссылка: https://github.com/jeffmo/es-class-fields-and-static-properties

Instance поле Процесс инициализации

Процесс выполнения поля инициализатору происходит во время создания экземпляра класса. Ниже описывается процесс инициализации каждого инициализатора поля класса (предназначенный для запуска один раз для каждого поля в том порядке, в котором они объявлены):

  • Позволяет экземпляру быть экземпляром объекта.
  • Позволяет fieldName быть именем текущего поля (как указано в слоте функции конструктора).
  • Пусть fieldInitializerExpression является выраженным выражением инициализатора для текущего поля (как хранится в слоте функции конструктора).
  • Пусть initializerResult будет результатом вычисления поляInitializerExpression с равным экземпляру.
  • Пусть свойствоDescriptor будет PropertyDescriptor {[[Value]]: initializerResult, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: false}. Экземпляр вызова. [[DefineOwnProperty]] (fieldName, propertyDescriptor).
+1

Ничего в этом вопросе не о предлагаемом синтаксисе свойств класса ES. – loganfsmyth

+0

Это неверно, спецификация [link] (https://www.ecma-international.org/ecma-262/6.0/# sec-method-определения-runtime-semantics-propertydefinitionevaluation) и все основные браузеры, которые они настраивают: true и enumerable: false. Для свойств на объектных литералах перечислимое истинно –

-1

Ну, очевидно, это касается конструкторов. Когда вы игнорируете конструктор, свойство, которое вы определяете с помощью getter, создается на прототипе конструкторов, следовательно, правильный способ выполнения задания, вероятно, должен выглядеть следующим образом:

class a { 
    get b() { 
     delete this.constructor.prototype.b; 
     return this.constructor.prototype.b = 1; 
    } 
} 
z = new a(); 
z.b; // 1 
+0

Ссылка на 'this.constructor.prototype', как правило, плохая идея, когда дело доходит до подклассы. Просто укажите ссылку «a.prototype», если это то, что вы имеете в виду. – Bergi

+0

В какой среде вы это выполняете? Как указывает Джереми выше, это должно выбросить ES6. – Bergi

Смежные вопросы