Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is using closures to emulate encapsulation a bad idea?

For example, take a look at my simple implementation of a stack:

var MyStack = (function() {
    var min;
    var head;

    // Constructor
    function MyStack() {
        this.size = 0;
    }

    MyStack.prototype.push = function(val) {
        var node = new Node(val);

        if (typeof min === 'undefined' || val < min) {
            min = val;
        }

        ++this.size;
        if (typeof head === 'undefined') {
            head = node;
        } else {
            node.next = head;
            head = node;
        }
    };

    MyStack.prototype.pop = function() {
        if (typeof head === 'undefined') {
            throw new Error('Empty stack');
        }

        --this.size;

        var data = head.data;
        head = head.next;

        return data;
    };

    MyStack.prototype.min = function() {
        if (typeof min === 'undefined') {
            throw new Error('Min not defined');
        }

        return min;
    };

    MyStack.prototype.peek = function() {
        if (typeof head === 'undefined') {
            throw new Error('Empty stack');
        }

        return head.data;
    };

    function Node(data) {
        this.data = data;
        this.next;
    }

    return MyStack;
})();

By using this method, I can make sure that no one is able to (accidentally or intentionally) manipulate "private" fields such as min and head. I can also make use of private functions such as Node() which doesn't need to be exposed.

I have read that this will use more memory just because of the fact that it has to maintain an additional scope for each new object that is created for MyStack. Does it need so much extra memory that this way is a bad idea?

I did try to optimize it by making use of prototypes instead of creating functions every time a new object is created. In other words, I didn't include the functions as part of the constructor of MyStack.

My question is, is this poor design? Are there are any major downfalls to this methodology?

like image 318
gjvatsalya Avatar asked Oct 20 '16 22:10

gjvatsalya


2 Answers

Is using closures to emulate encapsulation a bad idea?

No. Although I wouldn't consider this to be "emulation", closures are implementing encapsulation.

I did try to optimize it by making use of prototypes instead of creating functions every time a new object is created. In other words, I didn't include the functions as part of the constructor of MyStack.

My question is, is this poor design? Are there are any major downfalls to this methodology?

Yes, that's actually wrong. Your min and head (and MyStack and Node) variables are essentially static. They are defined only once, and will be shared by all instances. You cannot create two distinct stacks, they both will have the same head reference.

To encapulate per-instance state, you will need to declare the variables in the constructor so that they will be created with every new object. For that, you'll have to also declare all methods that need to access them ("privileged") in the constructor scope.

var MyStack = (function() {
    function MyStack() {
        var size = 0;
        var head = undefined;

        function checkNonEmpty() {
            if (typeof head === 'undefined') {
                throw new Error('Empty stack');
            }
        }
        this.push = function(val) {
            size++;
            head = new Node(val, head);
        };
        this.pop = function() {
            checkNonEmpty();
            this.size--;
            var data = head.data;
            head = head.next;
            return data;
        };
        this.peek = function() {
            checkNonEmpty();
            return head.data;
        };
        this.getSize = function() {
            return size;
        };
    }

    function Node(data, next) {
        this.data = data;
        this.next = next;
    }

    return MyStack;
})();

If you want to put these methods on the prototype, you will need to make the head and size values available as properties of the instance.

like image 105
Bergi Avatar answered Sep 20 '22 13:09

Bergi


Considering that encapsulation is one of the principles of of Object Oriented Programming, I don't think this is a bad coding practice. Closures in JavaScript are your means of encapsulating variables and restricting access to other parts of the application.

In a lot of ways, nothing is truly secure in JavaScript. Even with a closure, those variables you want keep private are accessible via different means in different browsers. For example, in Google Chrome, you can set a break-point in the debugger and get access to any variable within the active enclosure. Although we can do a great deal within the browser to ensure security, we are still dealing with an interpreted language that is compiled on the machine running the code.

And considering your example: var MyStack = (function(){...})(); If you ever work with typescript or any rapid development frameworks, you will see that this is the output coding method used to namespace objects when the frameworks compile/transpile.

like image 38
msinnes Avatar answered Sep 20 '22 13:09

msinnes