以下代码仅针对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' });

答案 0 :(得分:5)
您无法修改函数的name
属性。描述符表示它不是writable
...
var BaseClass = function (data) {
Object.assign(this, data);
};
console.log(Object.getOwnPropertyDescriptor(BaseClass, 'name'));

但由于它是configurable
,您可以使用Object.defineProperty()
。
var BaseClass = function (data) {
Object.assign(this, data);
};
Object.defineProperty(BaseClass, 'name', {
writable: true,
value: 'Foo'
});
console.log(BaseClass.name);

修改强>
我回来了!所以......正如我之前在评论中所说,我认为我已经确定了你的问题。我的回答有点太快,并没有看出你的ES5继承是错误的。
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' });

在您的代码中,this
是一个函数,并引用BaseClass
。这就是为什么不允许你修改它的名字......
事实上,在JavaScript中使用继承时,通常需要以下两行:
ExtendedClass.prototype = Object.create(BaseClass.prototype);
ExtendedClass.prototype.constructor = ExtendedClass;
这是一个有效的实现:
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

答案 1 :(得分:3)
name
是您要将其设置为的Function
对象的保留属性。您无法设置它。
name属性的文档位于MDN。
答案 2 :(得分:2)
如果您在 Angular + Typescript + NgRX 中遇到此错误:
您可以使用传播运算符对只读对象进行浅表复制以使其可读,但是根据您的情况,您可能不希望这样做。
let x = [...y];
如果您使用Redux / NgRX,则选择器有可能会返回一个带有对存储的引用的只读对象,当尝试通过模板绑定更改该对象属性时,该对象可能会引发异常。根据您的情况,您可以进行深拷贝以删除商店参考。
let x = JSON.parse(JSON.stringify(y));
答案 3 :(得分:1)
如果您在 Angular + TypeScript 中出现此错误:
错误/无效:
@Output whatever_var = new EventEmitter();
好/正确:
@Output() whatever_var = new EventEmitter();
答案 4 :(得分:1)
使用ES7 +或TypeScript扩展运算符功能来克服此问题
obj = { ...obj, name: { first: 'hey', last: 'there'} }
答案 5 :(得分:0)
我在Angular中遇到了这个问题,同时从ActivatedRoute的queryParams中设置了一个局部变量,并试图有条件地覆盖或合并...事先复制就可以了:
updateQp(qp = {}, force = false) {
let qpLoc = Object.assign({}, this.queryParamsLocal)
this.queryParamsLocal = force ? qp : Object.assign(qpLoc, qp)
}