JavaScript类仅含getter无setter报错及同名属性疑问
1. 报错代码分析
这段代码触发TypeError的核心是属性名冲突+缺少对应setter:
class Book { constructor(author) { this.author = author; } // getter get author() { return this.author; } } const novel = new Book('anonymous'); console.log(novel.author); // TypeError: Cannot set property author of #<Book> which has only a getter
当你在类中定义get author()时,会在类的原型上创建一个仅含getter的访问器属性author。此时构造函数里的this.author = author,本质是试图给这个访问器属性赋值,但因为没有定义对应的set author(),JavaScript会直接抛出错误。
另外注意:即使没有赋值报错,get author()里return this.author也会导致无限递归——调用getter时又会读取this.author,再次触发getter,直到栈溢出。
2. 无报错代码分析
修改getter名称后不再报错,是因为访问器属性和实例自有属性名称不冲突:
class Book { constructor(author) { this.author = author; } // getter get writer() { // 仅修改了名称 return this.author; } } const novel = new Book('anonymous'); console.log(novel.writer); // anonymous
这里构造函数里的this.author = author是给实例添加了一个自有属性author,而get writer()是原型上的访问器属性,两者名称不同。赋值操作只会给实例的author属性赋值,不会触发任何访问器的setter(你既没定义set writer(),也没给writer属性赋值)。调用novel.writer时,会执行getter读取实例的author属性值,自然不会报错。
3. 补充疑问解答
这段代码不报错的原因是赋值的属性和访问器属性名称完全不同:
class Book { constructor(name) { this._author = name; } // getter get author() { return this._author; } } let a = new Book("Mike") console.log(a.author)
构造函数里赋值的是this._author(实例的自有属性),而你定义的访问器属性是author。整个过程中你从来没有试图给author这个访问器属性赋值,自然不会触发“仅含getter无setter”的报错。调用a.author时,只是执行getter读取_author的值,完全合法。
内容的提问来源于stack exchange,提问作者Mira Ling

