How do I redefine a property from a prototype?
Asked Answered
C

2

1

How do I remove the property p from the object's prototype?

var Test = function() {};
Object.defineProperty(Test.prototype, 'p', {
  get: function () { return 5; }
});

Object.defineProperty(Test.prototype, 'p', {
  get: function () { return 10; }
});

This produces TypeError: Cannot redefine property: p. Is there a way I can remove the property and re-add it? Or is it possible to set the configurable attribute after the property was created?

Coronograph answered 29/1, 2015 at 15:29 Comment(9)
Sure, you need to define it as configurable.Photomap
The original definition isn't mine, so I can't do that. The property is defined in an external library.Coronograph
Can you extend the prototype chain one level deeper (inherit from Test and put your property in the middle) or override it on the instance (that is do function MyTest(){ t = new Test(); t.p = ...; return t; }Photomap
No. I am trying to inject a bugfix in a library, after it's loaded and before it's execution.Coronograph
Are you able to run code before that code? Or must it be after?Minetta
@Oriol: Any time. I just can't change the original code.Coronograph
@Coronograph by design - unless you can change the original code or override Object.defineProperty itself this is impossible.Photomap
The point of having configurable being toggle-able and in defineProperty is to prevent what you're trying to do. It exists to prevent a property from being changed or removed.Jest
Of course like I said you can do something like var oldTest = Test; Test = function(){ var t = new oldTest; t.p = 10; return t;}Photomap
M
3

If you are able to run code before the code you want to avoid, you can try hijacking Object.defineProperty to prevent adding that property:

var _defineProperty = Object.defineProperty;
Object.defineProperty = function(obj, prop, descriptor) {
    if(obj != Test.prototype || prop != 'p')
        _defineProperty(obj, prop, descriptor);
    return obj;
};

Or you can make it configurable, to be able to modify it later:

var _defineProperty = Object.defineProperty;
Object.defineProperty = function(obj, prop, descriptor) {
    if(obj == Test.prototype && prop == 'p')
        descriptor.configurable = true;
    return _defineProperty(obj, prop, descriptor);
};

At the end, you can restore the original one:

Object.defineProperty = _defineProperty;
Minetta answered 29/1, 2015 at 15:44 Comment(1)
This is a terrible solution, but it is the only one I've found and it seems to work fine, so I'll go with it.Coronograph
M
1

Have you tried something like this? It would have to run before new Test instances are created though.

var Test = function () {};

Object.defineProperties(Test.prototype, {
    p: {
        get: function () {
            return 5;
        }
    },

    a: {
        get: function () {
            return 5;
        }
    }
});

Test.prototype = Object.create(Test.prototype, {
    p: {
        get: function () {
            return 10;
        }
    }
});

var t = new Test();

console.log(t.a, t.p);
Mitman answered 29/1, 2015 at 15:45 Comment(2)
This should work, and you could define the property as an argument of Object.create rather than call Object.defineProperty afterwards. jsfiddle.net/Xotic750/j66peg0zHabana
@Habana Yes, I was just too lazy not to copy/paste so once again I just copy/pasted yours ;)Mitman

© 2022 - 2024 — McMap. All rights reserved.