简体   繁体   中英

Why do lazy getters work with prototypes but not with classes?

Consider the following code:

 const defclass = prototype => { const constructor = prototype.constructor; constructor.prototype = prototype; return constructor; }; const Person = defclass({ constructor: function Person(firstname, lastname) { this.firstname = firstname; this.lastname = lastname; }, get fullname() { delete this.fullname; // doesn't delete on instances return this.fullname = this.firstname + " " + this.lastname; } }); const john = new Person("John", "Doe"); const jane = new Person("Jane", "Doe"); console.log(john.fullname); // John Doe console.log(jane.fullname); // Jane Doe 

This works because the property assignment on this shadows the non-existent setter.


Now, consider the same code using ES6 classes:

 class Person { constructor(firstname, lastname) { this.firstname = firstname; this.lastname = lastname; } get fullname() { delete this.fullname; // doesn't delete on instances return this.fullname = this.firstname + " " + this.lastname; } } const john = new Person("John", "Doe"); const jane = new Person("Jane", "Doe"); console.log(john.fullname); // throws an error because there is no setter console.log(jane.fullname); 

The reason why it doesn't work is explained in the this answer . It's because we find the property in the prototype chain and it doesn't have a setter. So, why isn't the same error thrown when we use regular prototypes?

Note: You can delete the line with the delete keyword without affecting the behavior of the code.

I do get the same error with the first code:

 const defclass = prototype => { const constructor = prototype.constructor; constructor.prototype = prototype; return constructor; }; const Person = defclass({ constructor: function Person(firstname, lastname) { this.firstname = firstname; this.lastname = lastname; }, get fullname() { "use strict"; // ^^^^^^^^^^^^ return this.fullname = this.firstname + " " + this.lastname; } }); const john = new Person("John", "Doe"); const jane = new Person("Jane", "Doe"); console.log(john.fullname); // John Doe console.log(jane.fullname); // Jane Doe 

It's just that class code is in strict mode by default.

In sloppy mode, the assignment doesn't work but is ignored and the right hand side value is return ed from the getter. Accessing .fullname again would run the getter again.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM