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

后端 未结 6 1515
攒了一身酷
攒了一身酷 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

提交回复
热议问题