Question

I believe I understand the benefit of getters and setters on objects, which is obscuring access to your properties directly. However, because arrays will return a reference to an object, we can seemingly set them using the "getter" method. Is there a way to avoid this?

I'm assuming because this is because objects are passed by reference rather than copied, but I'm not positive.

var Obj = function() {
    var myVal = 20;
    var myArr = [1, 2, 3];

    this.myVal = function() {
        return myVal;
    };

    this.myArr = function() {
        return myArr;
    };
};

var myObj = new Obj();

console.log(myObj.myVal()); // 20
myObj.myVal() = 50; // error on the left hand assignment


console.log(myObj.myArr()); // [1, 2, 3]
myObj.myArr()[1] = 50; // the assignment works!
console.log(myObj.myArr()); // [1, 50, 3]
Was it helpful?

Solution

What you're doing in your example is not getters/setters in JavaScript, you're setting a function on an object that creates a closure over two 'private' members of that object (and you're leaking a reference for the array). You could refer to helper functions as 'getters' and 'setters' as you would in another language, but this could lead to confusion.

Helper functions would look like this:

var Obj = function() {
    var myVal = 20;

    this.getVal = function() {
        return myVal;
    };

    this.setVal = function(val){
        // validation of val
        myVal = val;
    };
};

There are quite a few different ways to define 'getters and setters', I recommend you check out MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects#Defining_Getters_and_Setters

This is one of my more favorite ways:

var o = { a:0 }
Object.defineProperties(o, {
    "b": { get: function () { return this.a + 1; } },
    "c": { set: function (x) { this.a = x / 2; } }
});
o.c = 10 // Runs the setter, which assigns 10 / 2 (5) to the 'a' property
console.log(o.b) // Runs the getter, which yields a + 1 or 6

edit
Remember, a constructor function will either return itself (the object created by the function) or an object returned from the function. You can use that to use the Object.defineProperties on some object o, then just return o at the end of the constructor function.
/edit

References

To answer your question about leaking the internal array reference outside of the helper function, I'd recommend cloning the array. You'll need to also consider that the internals of the of array may also be object references instead of primitives and determine how far you want to lock this 'private' state of your object.

Personally, I use frameworks and clone functionality. For instance, you can use underscore.js's clone()

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top