1

I have a need for the following functionality. I want to freeze the existing properties of an object, but allow for new properties to be added. For some reason, there seems to be no Object.freezeExisting() functionality, and I think it may be worthwhile to implement that, with the option of freezing existing properties of the prototype.

I have no idea how to do that. This is some code to get started, but this cannot be right at all. I don't care about performance that much, it just has to work 100%.

Object.freezeExistingProps = function(obj, modifyProto){

    Object.keys(obj).forEach(function(key){

        const val = obj[key];

        Object.defineProperty(obj, key , {  //we simply overwrite existing prop
            value: val,
            writable: false, // important, I think
            enumerable: true,
            configurable: false
        });


    });

    return obj;

};

But I just need a sanity check on the above. I also need some info on how one could go down the prototype chain and somehow stop before messing with the actual Object.prototype.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
Alexander Mills
  • 90,741
  • 139
  • 482
  • 817
  • `hasownproperty` is the one I guess you are looking for. – Jai May 23 '16 at 09:27
  • Possible duplicate of [Javascript: Object doesn't support method 'freeze'](http://stackoverflow.com/questions/13117771/javascript-object-doesnt-support-method-freeze) – Vladu Ionut May 23 '16 at 09:38
  • 1
    "*freezing existing properties of the prototype*" doesn't make much sense. If you don't prevent extensions, the prototype can be swapped out for some other object anyway. And your intention to freeze only parts of the prototype chain makes this even more questionable. You might want to consider copying the inherited properties onto the object itself and then freezing those. – Bergi May 23 '16 at 15:17

1 Answers1

3

You can easily implement the setIntegrityLevel algorithm without preventing extensions yourself:

Object.freezeExisting = function(o) {
    for (const key of Reflect.ownKeys(o)) {
        const desc = Object.getOwnPropertyDescriptor(o, key);
        if (!desc)
            continue;
        if ("value" in desc)
            Object.defineProperty(o, key, {configurable: false, writable: false});
        else
            Object.defineProperty(o, key, {configurable: false});
    }
    return o;
};
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • You removed the "If *currentDesc* is not undefined" check from the spec. But it can be necessary with proxies like `new Proxy({},{ownKeys:()=>["a"]})` which lie about their properties. – Oriol Jun 05 '16 at 18:59
  • @Oriol: Oh, I tried hard to find a case where `currentDesc` would be `undefined` for keys from `ownKeys`, and failed. But you're right, proxies could do this. Updated. – Bergi Jun 05 '16 at 21:10