1

I have an object which is initialized like

  var x = function(){
       var result = 5,
       clear = function(){
          result = 0;
        };
      return {
        result: result,
        clear: clear      
     }           
  }

I am later creating a new instance of x using var y = new x();

but when i try setting the value y.result = 5; and want to clear the result value to 0 I call y.clear();

However it is not resetting the y.result to 0... Not sure why?

Anything that i am doing wrong?

11
  • 3
    Numbers are immutable, the result on top is not the same as result in the object you're returning. Make a getter function. Commented Aug 14, 2014 at 2:11
  • 1
    You should be using var y = x();, not var y = new x();. x is not a constructor function. (It does not write to this.) Commented Aug 14, 2014 at 2:13
  • how would that look like? Commented Aug 14, 2014 at 2:13
  • 1
    clear is a setter because it sets the result variable. A getter would return the result variable. Commented Aug 14, 2014 at 2:15
  • 1
    And ladies and gentlemen, this is why Douglas Crockford doesn't like new. Commented Aug 14, 2014 at 2:17

2 Answers 2

3

Within your function:

var x = function(){
       var result = 5,
       clear = function(){
          result = 0;

The identifier result in this function has a closure to the variable result in the outer function (i.e. outer execution context).

        };
      return {
        result: result,

That assigns the value of the variable named result to the object property named result.

        clear: clear      
     }           
  }

So later when you call y.clear() you are setting the value of the variable held in the closure, which does not update the object property named result.

If you want x to be a constructor, then:

function X() {
  this.result = 5;
  this.clear = function() {
    this.result = 0;
  }
}

So now:

var y = new X();
y.clear();
console.log(y.result); // 0

Note that it is convention for constructors to have a name starting with a capital letter. You can learn more about how to use the new operator on MDN.

To leverage ECMAScript inheritance, put the clear function on the constructor's prototype so that all instances inherit the one method, rather than each having its own:

function X() {
  this.result = 5;
}

X.prototype.clear = function() {
  this.result = 0;
}
Sign up to request clarification or add additional context in comments.

Comments

1

The problem is that numbers are referenced by value. Assigning value to result variable from clear function won't change value of result on new x instance.

There are several ways to go about this:

  1. Store data on this, then modify it there inside constructor and method, I find it easier to understand and more readable. This is probably what you wanted to begin with:

    function x () {
        this.result = 5;
    }
    
    x.prototype.clear = function () {
        this.result = 0;
    }
    
    var z = new x();
    // z.result === 5
    z.clear()
    // z.result === 0;
    
  2. Define getter and setter on returned object, so instance result would return\set closured variable:

    function x () {
        var result = 5;
    
        function clear () {
            result = 0;
        }
    
        var out = {
            clear: clear
        };
    
        Object.defineProperty(out, "result", {
            get: function () {
                return result;
            },
            set: function (value) {
                result = value;
            }
        });
    
        return out;
    }
    
    var z = new x();
    // z.result === 5
    z.clear()
    // z.result === 0;
    z.result = 10
    // z.result === 10;
    z.clear()
    // z.result === 0;
    

1 Comment

Not, IE7/8 do not support defineProperty on objects. The first solution should work there just fine, though. If you really want to go with closured var approach, then all external access to result should be done using function(s).

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.