Cannot assign to read only property 'name' of object '[object Object]'

后端 未结 6 1513
攒了一身酷
攒了一身酷 2021-02-04 03:19

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

相关标签:
6条回答
  • 2021-02-04 03:55

    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

    0 讨论(0)
  • 2021-02-04 03:55

    Used ES7+ or TypeScript spread operator feature to overcome this

    obj = { ...obj, name: { first: 'hey', last: 'there'} }
    
    0 讨论(0)
  • 2021-02-04 03:57

    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));
    
    0 讨论(0)
  • 2021-02-04 03:57

    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.

    0 讨论(0)
  • 2021-02-04 04:04

    If you get this error in Angular+TypeScript:

    WRONG / INVALID:

    @Output whatever_var = new EventEmitter();

    GOOD / CORRECT:

    @Output() whatever_var = new EventEmitter();

    0 讨论(0)
  • 2021-02-04 04:13

    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)
    }
    
    0 讨论(0)
提交回复
热议问题