1

I was wondering if it is possible to access foo from window.updateFoo() in the code below:

function f1 () {
    'use strict';
    this.x = {};
    this.x.foo = 0;

    window.updateFoo = function(val){
       this.x.foo = val;       // Obviously wrong since 'this' doesn't refer to f1 now. Uncaught TypeError: Cannot set property 'foo' of undefined 
    };
    window.updateFoo(20);      // Try changing the value of this.x.foo?
}
kaushal
  • 785
  • 12
  • 27

4 Answers4

2

When you call window.updateFoo, it is called in the context of window. Your best option is to save this in a variable, and then use that in the function:

function f1 () {
    'use strict';
    this.x = {};                // Object for 'const' variables
    this.x.foo = 0;

    var _this = this;

    window.updateFoo = function(val){
       _this.x.foo = val;       // Use saved version
    };
    window.updateFoo(20);      // Try changing the value of this.x.foo?
}

The other option, but it will only work within f1, is to call updateFoo will a specific context:

window.updateFoo.call(this, 20);
Scimonster
  • 32,893
  • 9
  • 77
  • 89
1

Yes, you are creating a closure. In a closure, the inner function has access to the outer functions variables. However, you should create another variable to reference function f1 because the context of this will be wrong. When you call a function directly, this refers to the global object, or window.

function f1(){
    'use strict';
    this.x = {};                // Object for 'const' variables
    this.x.foo = 0;
    var that = this;

    window.updateFoo = function(val){
       that.x.foo = val;       // Obviously wrong since 'this' doesn't refer to f1 now. Uncaught TypeError: Cannot set property 'foo' of undefined 
    };
    window.updateFoo(20); 
}
What have you tried
  • 11,018
  • 4
  • 31
  • 45
1

You can also bind the context of "this", in the scope it sits, to the method you want.

window.updateFoo = function(val){
   this.x.foo = val;
}.bind(this)
james emanon
  • 11,185
  • 11
  • 56
  • 97
1

You can use bind()

Well, .bind() simply creates a new function that, when called, has its this keyword set to the provided value.

More on understanding bind here.

this.x = {}; 
this.x.foo = 0;
var func = function(val) {
   this.x.foo = val;
}.bind(this);

Like so:

function f1() {
    'use strict';
    this.x = {};                
    this.x.foo = 0;

    window.updateFoo = function(val) {
       this.x.foo = val;       
    }.bind(this);  

    window.updateFoo(10);
    alert(this.x.foo); // alerts '10'   
}

f1();

JSFiddle here.

Here's a little explanation:enter image description here

Yes Barry
  • 9,514
  • 5
  • 50
  • 69