Conor O'Brien
Conor O'Brien

Reputation: 1027

How to declare an object and its children as a constant?

Currently, I'm working on a project for my school whose purpose is to create an object pertaining to math; my object is similar to that of the Native Math object, and, as a result, I want to emulate certain aspects of it.

When using the console in Firefox, I have found that certain properties (e.g. E, PI, and SQRT2) cannot be edited (represented by a little lock on them). I know that there is a const declaration method, but I've tried both...

const obj = {
    prop: function(x){
        return x^3^4;
    },
    foo: "bar",
    bar: "foo"
}
obj.prop = -3.14;
print(obj.prop);    // prints "-3.14"

...and...

const unEditable = 2.718;
var obj = {e:unEditable};
obj.e = 3;
print(obj.e);    // prints "3"

Is there a way to define properties of an object such that said properties cannot be edited by a user? By that, I mean could I assign obj a variable e with a value 2.718 so that when a person assigns obj.e a value of "Hello, world!, obj.e would still return 2.718?

Notes:

Code Fragmant

var Θ = {};
Θ.e = 2.71828;
Θ.pi = 3.14159;
Θ.fac = function(num){
    if(!arguments.length) return NaN;
    return (num<2)?(num<0)?Infinity:1:num*Θ.fac(num-1);
}
Θ.nroot = function(n,m){
    return Θ.pow(n,1/m);
}

Conclusion

An answer based off of Wingblade's answer:

var Θ = {};
Object.defineProperties(Θ, {
    pi: {
        value: 3.14159,
        writable: false
    },
    e: {
        value: 2.71828,
        writable: false
    }
});
// rest of editable properties go after

Upvotes: 1

Views: 131

Answers (1)

Wingblade
Wingblade

Reputation: 10093

You can use obj.defineProperty to add a property to an object in a more advanced way that offers more control over how the property will behave, for example if it is writeable or not.

More on this here: MDN Object.defineProperty()

EDIT: For defining multiple properties at once you can use Object.defineProperties() like so:

var o = {};
Object.defineProperties(o, {
  "e": {
    value: 2.71828,
    writable: false
  },
  "pi": {
    value: 3.14159,
    writable: false
  },
  "fac": {
    value: function(num){
        if(!arguments.length) return;
        return (num<2)?(num<0)?Infinity:1:num*o.fac(num-1);
    },
    writable: false
  },
  "nroot": {
    value: function(n,m){
        return o.pow(n,1/m);
    },
    writable: false
  }
});

You can actually omit writeable: false for all properties, since it defaults to false when adding properties using Object.defineProperty, but it can be useful to leave it in for readability's sake (especially if you're new to this technique).

Upvotes: 2

Related Questions