4

I am going crazy over and over again on the same topic, variable scope. Creating a global variable on this didn't work, I tried returning the value in one function to use the other one, but always get 'undefined' error back in the console. This is a simplyfied markup of the code:

domElement.plugin({
    method1: function() {
        // create variable
        var myvar = 1;
        // other things going on here in this method
    },
    method2: function() {
        // use variable
        console.log(myvar);
    }
});

This is a jquery plugin where I am trying to access the value of var myvar created in method1 (and is variable) inside of method2. I have found several things here on the forums but can't seem to get any of them working, thus any help is more than appreciated.

Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
prettyInPink
  • 3,291
  • 3
  • 21
  • 32
  • 1
    That's a scoping issue, the variable is simply not visible in the other function. – Johannes Jander Feb 15 '16 at 16:36
  • Possible duplicate of [javascript: get a function's variable's value within another function](http://stackoverflow.com/questions/11813806/javascript-get-a-functions-variables-value-within-another-function) – Johannes Jander Feb 15 '16 at 16:38

4 Answers4

3

You can't, it won't be in scope anymore. You need to define your variable outside that scope and assign inside the function.

domElement.plugin({
    myvar:null,
    method1: function() {
        // create variable
        myvar = 1;
        // other things going on here in this method
    },
    method2: function() {
        // use variable
        console.log(myvar);
    }
});

It's mentioned in another comment that you could define the variable in one method, and then pass it to the other - but this only works if you plan on only using that second method from inside the first. The variable still won't be accessible from outside the method.

millerbr
  • 2,951
  • 1
  • 14
  • 25
  • Using the above code and logging the variable works for method1 but for the second one it returns an 'not defined' error (not undefined), could it be the plugin itself? – prettyInPink Feb 15 '16 at 16:57
  • Are you running method2 before or after method1? `myvar` will only have a value after method1 is called, unless you initialise it with a value at first. Can do this by doing `myvar:1,` instead of `myvar:null,` on line 2 of my example – millerbr Feb 15 '16 at 17:00
3

You need to either make the variable scope accessible to both methods:

domElement.plugin({
    myvar: null, 
    method1: function() {
        this.myvar = 1;
    },
    method2: function() {
        console.log(this.myvar); // = null or 1 depending on when you call this function
    }
});

Or you could pass it from one method to the other:

domElement.plugin({
    method1: function() {
        var myvar = 1;
        this.method2(myvar);
    },
    method2: function(v) {
        console.log(v); // = 1
    }
});

I would personally use the first example.

Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
  • Sorry, not my downvote.current, using the above code returns, method1: number is: NaN, and type is: number and method2: undefined – prettyInPink Feb 15 '16 at 16:57
  • I will try to recreate it in a fiddle. The plugin is a jquery slider, function1 runs each time the slider moves, this function gets a value externally (and logs it correctly), this value needs to be used inside function2, which runs each time the page reloads. The value of the var stays in memory thanks to api. Not sure if this makes any sense. – prettyInPink Feb 15 '16 at 17:03
  • Sorry had a small error in the code I used from your example, but it works great! thanks a million!!! – prettyInPink Feb 15 '16 at 20:40
2

Two simpliest way to do that:

Global scope:

var myvar;
domElement.plugin({
    method1: function() {
        // create variable
        myvar = 1;
        // other things going on here in this method
    },
    method2: function() {
        // use variable
        console.log(myvar);
    }
});

Don't use global scope too much, it's bit messy; better to use object:

Object property:

domElement.plugin({
    myVar: 1,
    method1: function() {
        // create variable
        this.myVar = 1;
        // other things going on here in this method
    },
    method2: function() {
        // use variable
        console.log(this.myVar);
    }
});

I encourage you to use the second method.

Julien Leray
  • 1,647
  • 2
  • 18
  • 34
1

It might seem a bit long winded, but you can create a shared scope for your methods by using an immediately invoked function expression...

// create shared scope for methods
var methods = (function() {
    // create variable in shared context
    var myvar;
    // define method1
    function method1() {
        // assign value to variable
        myvar = 1;
        // other things going on here in this method
    }
    // define method2
    function method2() {
        // use variable
        console.log(myvar);
    }
    // return methods
    return {
        method1: method1,
        method2: method2
    }
// execute the scope function immediately...
}());

// assign methods to plugin
domElement.plugin({
    method1: methods.method1,
    method2: methods.method2
});

This works because javascript is function scoped, not block scoped, and declaring the variable in a parent scope that both methods have access to means they will both operate on the same variable. Also, the variable remains private to the context of the scope, so can't be accessed and modified from outside. This pattern helps to manage arbitrary modules that can co-exist alongside each other without collision.

Billy Moon
  • 57,113
  • 24
  • 136
  • 237