Domino
Domino

Reputation: 6768

Should I enclose/delete variables declared in a constructor?

There's something that's been bugging me about JavaScript closures. Variables created with the var keyword still exist in memory once the constructor has completed its execution. Example:

function RangeCalculator(values) {
  var min = Infinity;
  var max = -Infinity;
  for (var i = 0; i < values.length; ++i) {
    min = Math.min(min, values[i]);
    max = Math.max(max, values[i]);
  }

  this.range = max - min;
  
  this.getMin = function() {
    return min;
  };
  this.getMax = function() {
    return max;
  };
}

r = new RangeCalculator([1, 2, 3, 4, 5]);
console.log("min: " + r.getMin() + ", max: " + r.getMax());
<p>Check the console</p>

In that code, min and max aren't accessible from anywhere except functions defined within the constructor. This allows making private member variables in JavaScript.

But what if I just wanted to use the min and max variables to help me count the range, but didn't need them afterward. What if I remove the getMin and getMax functions. Will all the var-declared variables used in the constructor still exist and take space in memory, including the i from the for loop?

What if I wrap that code in a self-executing anonymous function?

function RangeCalculator(values) {
    (function (t) {
        var min = Infinity;
        var max = -Infinity;
        for (var i = 0; i < values.length; ++i) {
            min = Math.min(min, values[i]);
            max = Math.max(max, values[i]);
        }
        t.range = max - min;
    })(this);
}

var r = new RangeCalculator([1, 2, 3, 4, 5]);
alert(r.range);

Upvotes: 0

Views: 73

Answers (1)

Peter Seliger
Peter Seliger

Reputation: 13387

If information hiding is part of the custom type's concept, then the answer is definitely yes. Nevertheless a constructor should always be implemented as most lightweight as possible. All additional build logic should be part of a factory method. The given example code could be refactored towards something similar like the following ...

var NumberRange = (function (global) {

    var
        Number    = global.Number,
        Math      = global.Math,

        math_min  = Math.min,
        math_max  = Math.max,

        MIN_VALUE = Number.NEGATIVE_INFINITY,
        MAX_VALUE = Number.POSITIVE_INFINITY,

        collectLimitingValues = function (collector, value) {
            collector.minValue = math_min(collector.minValue, value);
            collector.maxValue = math_max(collector.maxValue, value);
            return collector;
        },


        NumberRange = function NumberRange (min, max) {
            this.range = (max - min);

            this.getMin = function () {
                return min;
            };
            this.getMax = function () {
                return max;
            };
        },


        createNumberRange = function (numberValueList) {

        //  right place for sanitizing all arguments.

            var rangeLimitMap = numberValueList.reduce(
                collectLimitingValues, {
                    minValue: MAX_VALUE,
                    maxValue: MIN_VALUE,
                }
            );
            return (new NumberRange(
                rangeLimitMap.minValue,
                rangeLimitMap.maxValue
            ));
        }
    ;

    return {
        create: createNumberRange
    };

}(window));


var r = NumberRange.create([1, 2, 3, 4, 5]);
console.log("min: " + r.getMin() + ", max: " + r.getMax());
<p>Check the console</p>

Upvotes: 1

Related Questions