简体   繁体   中英

Making primitive data types readOnly/nonConfig in JavaScript

Does anyone have any example implementation of making individual object props readOnly/non-configurable? I mean primitive data types. Have tried using ES5 Object API, but hitting a brick wall.

I can't show code, because it's still at that "messy" phase, but basically I'm iterating through an outside object which, itself, holds numeruos objects. Those objects each hold various primitive data types. I have made the outer objects readOnly, non-config, etc, but can't figure out how to do likewise for individual props, the innermost props.

So, if outer.inner.prop === "Hello" , I want to make that value readOnly .

Thanks!

UPDATE

I just figured this out, it was all in the for loop I was using to iterate over props. Now I've actually get data descriptors for the props, even the primitive ones. :) Thanks all!

You have to iterate through the inner object, since there is no way to deep-freeze an object using standard ES5 methods.

function deepFreeze(obj) {
    Object.keys(obj).forEach(function (key) {
        if (typeof obj[key] == 'object')
            deepFreeze(obj[key]);
    });
    Object.freeze(obj);
}

Edit: Also works for defineProperty if you don't want to freeze :

function deepWriteProtect(obj) {
    Object.keys(obj).forEach(function (key) {
        if (typeof obj[key] == 'object')
            deepWriteProtect(obj[key]);
        Object.defineProperty(obj, key, { writable: false });
    });
}

I'm not 100% sure I understand your question correctly, but from what I gather you are asking for private variables. If so, that can be easily achieved using closures.

function myClass(){
    var mySecretProperty = 10;
    this.getMySecretProperty = function(){
         return mySecretProperty;
    }
    this.changeMySecretProperty = function(s){
         // whatever logic you need for a setter method
         mySecretProperty = s;
    }
}

var myObj = new MyClass();
myObj.changeMySecretProperty(120);
myObj.getMySecretProperty(); // will return 120
myObj.mySecretProperty // will return undefined

Would the following (ES5) example help? It creates an empty constructor, with a getter for property a (and no setter, so de facto a is read only):

var Obj = function(){};
Obj.prototype = {
    get a() {return 5;}
}
var x = new Obj;
alert(x.a); //=> 5
x.a = 6; //=> TypeError: setting a property that has only a getter

Not using ES5 you can do

var Obj = function(){
  var a = 5;
  if (!Obj.prototype.getA) {
     Obj.prototype.getA = {
         toString: function() {
            return a;
         }
     };
  }
}

var y = new Obj;
alert(y.getA); //=> 5

But that is not 100% failsafe: Obj.prototype.getA can be overwritten.

Here is a jsfiddle showing how you can use ES5 getter/setter definitions to make a property of an object something that can only be fetched. The code looks like this:

var object = {
    get x() {
        return 17;
    }, set x() {
        alert("You cannot set x!");
    }
};

Of course the getter could obtain the value of the property ("x") from anywhere, like a closure from a constructor or something. The point is that the setter simply does not change the value, so attempts to change it:

object.x = 100;

will not have any effect.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM