0

So I've been studying javascript and I'm looking at closures now. I thought I had understood all the concept but I'm obviously missing something. For just studying purposes I created this closure that basically behaves like a class with an Object and an integer member. The code is as follows:

var AllFilters = (function () {

        var _length = 0;
        var _filters = {};

        //Return new length.
        //Overwrites if exists.
        function _addFilter(filter) {
            _filters[filter.name] = filter;
            _length++; //test if it was actually incremented...
        }

        //Remove property from object.
        //Returns the removed propety value, or undefinned.
        function _removeFilter(filter) {

            var removed;

            if (filter.name !== undefined) {
                //Removed based on filter object;
                removed = _filters[filter.name];
                delete _filters[filter.name];
            } else {
                //Removed based on filter name;
                removed = _filters[filter];
                delete _filters[filter];
            }

            _length--; //teste if it was actually deleted...
            return removed;
        }

        //Param = filter name;
        //Returns undefined or filter;
        function _getFilter(filter) {
                return _filters[filter];
        }

        //Return all filters in an array.
        function _getAsArray() {

            var arr = [];

            for (var filter in _filters) {

                if (_filters.hasOwnProperty(filter)) {
                    arr.push(_filters[filter]);
                }
            }

            return arr;
        }

        return function () {

            return {

                addFilter: _addFilter,

                removeFilter: _removeFilter,

                getFilter: _getFilter,

                getAsArray: _getAsArray,

                length: _length

            };
        };

    }());

Using:

x = AllFilters();
x.addFilter({ name: "a", foo: "bar" });
x.addFilter({ name: "b", foo: "baz" });
x.addFilter({ name: "c", foo: "qux" });

Everything works perfectly, except the length: it always returns zero, I want to make it return the current value, like a static var. The _filters var is returned correctly, it is not always reset like the length, so I really have no idea what is going on here, I thought _length would keep its state just like _filters does. Any thoughts?

1 Answer 1

1

When you update the _length variable it doesn't change the x.length property. That was initialized with the length when you created the object, but you never update it. You need to make that property a function that returns the length from the closure variable:

function _getLength() {
    return _length;
}
...
length: _getLength

Then you can use x.length() to get the current length.

Sign up to request clarification or add additional context in comments.

3 Comments

Damn I had tried that, but it didn't work. Now I realized that I was calling x.length instead of x.length() when I put it inside a fcuntion... Still I don't quite get why just using the variable does not work.. If I do filters: _filters and get it as x.filters, the object returned is up to date, so why isnt length?
Because a number is not an object. Numbers are copied when assigned, they're not accessed by reference.
I see, so my inner function actually stored a copy of length, not its reference. That makes sense. Thank you!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.