Javascript 无法分配给对象“[object Object]”的只读属性“name”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/44288164/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Cannot assign to read only property 'name' of object '[object Object]'
提问by Konstantin Azizov
The following code will throw an error only for the nameproperty.
It could be fixed by specifying nameproperty as writable in Object.createarguments but I'm trying to understand why is this happening(and maybe there is a more elegant way to fix it).
以下代码将仅针对该name属性引发错误。可以通过name在Object.create参数中将属性指定为可写来修复它,但我试图理解为什么会发生这种情况(也许有更优雅的方法来修复它)。
var BaseClass = function (data) {
Object.assign(this, data);
}
var ExtendedClass = function () {
BaseClass.apply(this, arguments);
}
ExtendedClass.prototype = Object.create(BaseClass);
console.log(new ExtendedClass({ type: 'foo' }));
new ExtendedClass({ name: 'foo' });
采纳答案by Badacadabra
You cannot modify the nameproperty of a function. The descriptor says it is not writable...
您不能修改name函数的属性。描述符说它不是writable......
var BaseClass = function (data) {
Object.assign(this, data);
};
console.log(Object.getOwnPropertyDescriptor(BaseClass, 'name'));
But since it is configurable, you could use Object.defineProperty().
但既然是这样configurable,你就可以使用Object.defineProperty().
var BaseClass = function (data) {
Object.assign(this, data);
};
Object.defineProperty(BaseClass, 'name', {
writable: true,
value: 'Foo'
});
console.log(BaseClass.name);
EDIT
编辑
I'm back! So... As I said previously in comments, I think I have identified your problem. I answered a bit too fast and did not see that your ES5 inheritance is wrong.
我回来了!所以......正如我之前在评论中所说的,我想我已经确定了你的问题。我回答的有点太快了,没看出你的ES5继承是错误的。
ExtendedClass.prototype = Object.create(BaseClass);is not what you want to do. Doing so means the prototype of ExtendedClassbecomes a constructor function. This obviously generates an unexpected behavior.
ExtendedClass.prototype = Object.create(BaseClass);不是你想做的。这样做意味着 的原型ExtendedClass成为构造函数。这显然会产生意想不到的行为。
function BaseClass(data) {
console.log(this instanceof BaseClass); // "this" is not an instance of "BaseClass"
console.log(this instanceof Function); // "this" is a function
console.log(this.name); // "this" is "BaseClass"
Object.assign(this, data);
}
function ExtendedClass() {
BaseClass.apply(this, arguments);
}
ExtendedClass.prototype = Object.create(BaseClass);
new ExtendedClass({ type: 'foo' });
In your code, thisis a function and refers to BaseClass. That is why you are not allowed to modify its name...
在您的代码中,this是一个函数并引用BaseClass. 这就是为什么你不能修改它的名字......
In fact, when working with inheritance in JavaScript, you generally need these two lines:
实际上,在 JavaScript 中使用继承时,通常需要这两行:
ExtendedClass.prototype = Object.create(BaseClass.prototype);
ExtendedClass.prototype.constructor = ExtendedClass;
Here is a valid implementation:
这是一个有效的实现:
function BaseClass(data) {
console.log(this instanceof BaseClass); // "this" is an instance of "BaseClass"
console.log(this instanceof Function); // "this" is not a function
console.log(this.name); // "this" has no name yet
Object.assign(this, data);
}
function ExtendedClass() {
BaseClass.apply(this, arguments);
}
ExtendedClass.prototype = Object.create(BaseClass.prototype);
ExtendedClass.prototype.constructor = ExtendedClass;
var instance = new ExtendedClass({ name: 'foo' });
console.log(instance.name); // foo
console.log(BaseClass.name); // BaseClass
console.log(ExtendedClass.name); // ExtendedClass
回答by user12180028
If you get this error in Angular+Typescript+NgRX:
如果您在Angular+Typescript+NgRX 中遇到此错误:
You can use the spread operator to take a shallow copy of a readonly object to make it readable, however you may not want this depending on your situation.
您可以使用扩展运算符获取只读对象的浅拷贝以使其可读,但是根据您的情况,您可能不希望这样做。
let x = [...y];
If you're using Redux / NgRX, there's a chance your selector could be returning a readonly object with a reference to the store, which can throw exceptions when trying to alter that object property via template binding. Depending on your situation, you can take a deep copy to remove the store reference.
如果您使用的是 Redux / NgRX,则您的选择器可能会返回一个带有对存储的引用的只读对象,这在尝试通过模板绑定更改该对象属性时可能会引发异常。根据您的情况,您可以进行深层复制以删除商店引用。
let x = JSON.parse(JSON.stringify(y));
回答by Misaz
回答by J.M.I. MADISON
If you get this error in Angular+TypeScript:
如果您在Angular+TypeScript 中遇到此错误:
WRONG / INVALID:
错误/无效:
@Outputwhatever_var = new EventEmitter();
@输出whatever_var = new EventEmitter();
GOOD / CORRECT:
好/正确:
@Output()whatever_var = new EventEmitter();
@Output()whatever_var = new EventEmitter();

