views:

65

answers:

4

I would like to make an object's structure immutable, preventing its properties from being subsequently replaced. The properties need to be readable, however. Is this possible?

I'm sure there are no language features (along the lines of final in Java and sealed in C#) to support this but wondered whether there might be another mechanism for achieving the same result?

I'm looking for something along these lines:

var o = {
    a: "a",
    f: function () {
        return "b";
    }
};

var p = o.a;        // OK
o.a = "b";          // Error
var q = o.f();      // OK
o.f = function () { // Error
    return "c"; 
};
+3  A: 

the best thing you can do is hide your properties inside of a closure.

var getMap = function(){
  var hidden = "1";
  return {
    getHidden : function() { return hidden; }
  }
}

var f = getMap ();

alert(f.getHidden());

I took a stab at it. In the above code you will need to not just return hidden but copy it into a new object perhaps. maybe you can use jquery's extend to do this for you, so you will be returning a new object, not the reference. This may be completely wrong though =)

mkoryak
I need the properties to be accessible from outside the object (question updated to reflect).
Matthew Murdoch
@Matthew So create a public access function. See my answer.
Josh Stodola
edited answer to be like what you want
mkoryak
-1, Can still do `f.getHidden = function() { return "1"; };`
orip
+4  A: 

ECMAScript 5 will have seal() and freeze(), but there's no good way to do this with current JavaScript implementations.

Source.

EndangeredMassa
+1: `freeze()` sounds like what I'm after.
Matthew Murdoch
you are running version 5 ?!
mkoryak
I just mentioned it for reference. I do not actively program against ECMAScript 5.
EndangeredMassa
+2  A: 

As mkoryak said, you can create a closure to hide properties

function Car(make, model, color) {
    var _make = make, _model = model, _color = color; 

    this.getMake = function() {
        return _make;
    }

}

var mycar = new Car("ford", "mustang", "black");

mycar.getMake(); //returns "ford"
mycar._make; //error
Chetan Sastry
+2  A: 

Using var in an object constructor will create a private variable. This is essentially a closure. Then you can create a public function to access/modify it. More information and examples available on Private Members in Javascript by Douglas Crockford.

Josh Stodola
But then you can replace the function to return whatever you want.
EndangeredMassa
@Sean Sure it can be deleted/replaced, but it cannot be altered. I guess the bottom line is that there is no way to replace the function with something that would give direct access to the private var.
Josh Stodola