techdog
techdog

Reputation: 1481

How do you create a javascript class with immutable properties

This question is specifically about preventing unwanted properties from being added to a javascript "class". I have a class called Animal.

function Animal(){
this.name="";
this.type="";
//20 other properties
}

What would be the easiest way for a user to create their own Animal and add 20 properties. I want to also prevent the user from accidentally adding incorrect properties.

my current method:

    var myAnimal= new Animal();
    myAnimal.name="fluffy";
    myAnimal.type="cat";
    myAnimal.typo="cat";

//adding 20 more properties would require typing myAnimal 20 more times Plus if a user makes a typo it would add it as a new property.

I was hoping there would be something like this:

myAnimal=new Animal{
name:"fluffy",
type:"cat";
typo:"cat" //would throw an error
}

I've looked into Object.freeze Object.seal, Object.preventExtensions but not sure how they apply to classes.

Upvotes: 7

Views: 8340

Answers (2)

Peter
Peter

Reputation: 1822

You can use Proxy For this. You can set custom setter, what throw an Error when obj does not has the property. You can do the same with get too in that case no more undefined cause of typo.

function Animal() {
    this.name = "";
    this.type = "";
    
    return new Proxy(this, {
        set: function(obj, prop, value) {
            if (!obj.hasOwnProperty(prop))
            {
                throw Error("I don`t have this property: " + prop);
            }
            obj[prop] = value;
        }
    });
}

var cat = new Animal();
console.log(cat);
cat.name = "Rita";
console.log(cat);
cat.nama = "Rata";
console.log(cat);

Upvotes: 3

Ry-
Ry-

Reputation: 224913

You can Object.seal(this) at the end of the constructor to prevent new properties from being added:

function Animal() {
    this.name = "";
    this.type = "";
    // 20 other properties
    Object.seal(this);
}

and you can take an object with initial values in the constructor:

function Animal(initial) {
    this.name = "";
    this.type = "";
    // 20 other properties
    Object.seal(this);
    Object.assign(this, initial);
}

used like so:

myAnimal = new Animal({
    name: "fluffy",
    type: "cat",
    typo: "cat",
});

with the downside that the error doesn’t point directly at typo like it would if you used multiple assignment statements.

Upvotes: 11

Related Questions