The following code will throw an error only for the name
property.
It could be fixed by specifying name
property as writable in Object.create
You cannot modify the name
property of a function. The descriptor says it is not 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()
.
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.
ExtendedClass.prototype = Object.create(BaseClass);
is not what you want to do. Doing so means the prototype of ExtendedClass
becomes a constructor function. This obviously generates an unexpected behavior.
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, this
is a function and refers to BaseClass
. That is why you are not allowed to modify its name...
In fact, when working with inheritance in JavaScript, you generally need these two lines:
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
Used ES7+ or TypeScript spread operator feature to overcome this
obj = { ...obj, name: { first: 'hey', last: 'there'} }
If you get this error in 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.
let x = JSON.parse(JSON.stringify(y));
The name
is reserved property of Function
object to which you are trying to set it in. You cannot set it.
documentation for name property is at MDN.
If you get this error in Angular+TypeScript:
WRONG / INVALID:
@Output whatever_var = new EventEmitter();
GOOD / CORRECT:
@Output() whatever_var = new EventEmitter();
I ran into this issue in Angular, while setting a local variable from ActivatedRoute's queryParams, and attempting to conditionally either override or merge... Duplicating beforehand did the trick:
updateQp(qp = {}, force = false) {
let qpLoc = Object.assign({}, this.queryParamsLocal)
this.queryParamsLocal = force ? qp : Object.assign(qpLoc, qp)
}