How to pass down function with "this" keyword [duplicate] - javascript

I have a question concerning how the "this" pointer is treated in a nested function scenario.
Say I insert this following sample code into a web page. I get an error when I call the nested function "doSomeEffects()". I checked in Firebug and it indicates that when I am in that nested function, the "this" pointer is actually pointing to the global "window" object - which I did not expect. I must not be understanding something correctly because I thought since I declared the nested function within a function of the object, it should have "local" scope in relation to the function (i.e. the "this" pointer would be referring to the object itself like how it is in my first "if" statement).
Any pointers (no pun intended) would be appreciated.
var std_obj = {
options : { rows: 0, cols: 0 },
activeEffect : "none",
displayMe : function() {
// the 'this' pointer is referring to the std_obj
if (this.activeEffect=="fade") { }
var doSomeEffects = function() {
// the 'this' pointer is referring to the window obj, why?
if (this.activeEffect=="fade") { }
}
doSomeEffects();
}
};
std_obj.displayMe();

In JavaScript the this object is really based on how you make your function calls.
In general there are three ways to setup the this object:
someThing.someFunction(arg1, arg2, argN)
someFunction.call(someThing, arg1, arg2, argN)
someFunction.apply(someThing, [arg1, arg2, argN])
In all of the above examples the this object will be someThing.
Calling a function without a leading parent object will generally get you the global object which in most browsers means the window object.

Since this appears to be among the most upvoted questions of its kind, let me add, after all these years, the ES6 solution using arrow functions:
var std_obj = {
...
displayMe() {
...
var doSomeEffects = () => {
^^^^^^^ ARROW FUNCTION
// In an arrow function, the 'this' pointer is interpreted lexically,
// so it will refer to the object as desired.
if (this.activeEffect=="fade") { }
};
...
}
};

this is not part of the closure scope, it can be thought of as an additional parameter to the function that is bound at the call site. If the method is not called as a method then the global object is passed as this. In the browser, the global object is identical to window. For example, consider the following funciton,
function someFunction() {
}
and the following object,
var obj = { someFunction: someFunction };
If you call the function using method syntax such as,
obj.someFunciton();
then this is bound to obj.
If you call someFunction() directly, such as,
someFunction();
then this is bound to the global object, that is window.
The most common work around is to capture this into the closure such as,
displayMe : function() {
// the 'this' pointer is referring to the std_obj
if (this.activeEffect=="fade") { }
var that = this;
var doSomeEffects = function() {
// the 'this' pointer is referring to global
// that, however, refers to the outscope this
if (that.activeEffect=="fade") { }
}
doSomeEffects();
}

To understand this question , try to get the output for the following snippet
var myObject = {
foo: "bar",
func: function() {
var self = this;
console.log("outer func: this.foo = " + this.foo);
console.log("outer func: self.foo = " + self.foo);
(function() {
console.log("inner func: this.foo = " + this.foo);
console.log("inner func: self.foo = " + self.foo);
}());
}
};
myObject.func();
The above code will output the following to the console:
outer func: this.foo = bar
outer func: self.foo = bar
inner func: this.foo = undefined
inner func: self.foo = bar
In the outer function, both this and self refer to myObject and therefore both can properly reference and access foo.
In the inner function, though, this no longer refers to myObject. As a result, this.foo is undefined in the inner function, whereas the reference to the local variable self remains in scope and is accessible there. (Prior to ECMA 5, this in the inner function would refer to the global window object; whereas, as of ECMA 5, this in the inner function would be undefined.)

There's a difference between enclosure variables and "this". "this" is actually defined by the invoker of the function, while explicit variables remain intact inside the function declaration block known as the enclosure. See the example below:
function myFirstObject(){
var _this = this;
this.name = "myFirstObject";
this.getName = function(){
console.log("_this.name = " + _this.name + " this.name = " + this.name);
}
}
function mySecondObject(){
var _this = this;
this.name = "mySecondObject";
var firstObject = new myFirstObject();
this.getName = firstObject.getName
}
var secondObject = new mySecondObject();
secondObject.getName();
you can try it out here:
http://jsfiddle.net/kSTBy/
What's happening in your function is "doSomeEffects()", is being called explicitly, this means context or the "this" of the function is the window. if "doSomeEffects" was a prototype method e.g. this.doSomeEffects on say "myObject", then myObject.doSomeEffects() would cause "this" to be "myObject".

As explained by Kyle, you could use call or apply to specify this within the function:
Here is that concept applied to your code:
var std_obj = {
options: {
rows: 0,
cols: 0
},
activeEffect: "none",
displayMe: function() {
// the 'this' pointer is referring to the std_obj
if (this.activeEffect == "fade") {}
var doSomeEffects = function() {
// the 'this' pointer is referring to the window obj, why?
if (this.activeEffect == "fade") {}
}
doSomeEffects.apply(this,[]);
}
};
std_obj.displayMe();
JsFiddle

Since it wasn't mentioned I will mention that using .bind() is a solution -
doSomeEffects=doSomeEffect.bind(this);
doSomeEffects();
}
};
std_obj.displayMe();
Here is a more simple example -
bad = {
name:'NAME',
z : function() {
function x() { console.log(this.name); };
x()
}
};
bad.z() // prints 'undefined'
good = {
name:'NAME',
z : function() {
function x() { console.log(this.name); };
x=x.bind(this);
x();
}
};
good.z() // prints 'NAME'
It is true that using an arrow function => looks slicker and is easy for the programmer. However, it should be kept in mind that a lexical scope is likely to require more work in terms of processing and memory to setup and maintain that lexical scope, compared to simply associating a function's this with a pointer via .bind().
Part of the benefit of developing classes in JS was to provide a method to make this more reliably present and available, to pivot away from functional programming and lexical scopes, and thus reduce overhead.
From MDN
Performance considerations
It is unwise to unnecessarily create functions within other functions if closures are not needed for a particular task, as it will negatively affect script performance both in terms of processing speed and memory consumption.

It's because "this" refers to the self object / local function.
var std_obj = {
options : { rows: 0, cols: 0 },
activeEffect : "none",
displayMe : function() {
if (this.activeEffect=="fade") { }
let This = this; // 'this' here is for the std_obj scope. Create a reference to 'this' if you want to use it elsewhere.
var doSomeEffects = function() {
// 'this' here refers to the doSomeEffects scope. If you don't want "this," you can still use "this" of the std_obj scope.
if (This.activeEffect=="fade") { }
}
doSomeEffects();
}
};
std_obj.displayMe();

I also got a warning "Potentially invalid reference access to a class field via this"
class MyListItem {
constructor(labelPrm) {
this._flagActive = false;
this._myLabel = labelPrm;
labelPrm.addEventListener('click', ()=>{ this.onDropdownListsElementClick();}, false);
}
get myLabel() {
return this._myLabel
}
get flagActive(){
return this._flagActive;
}
onDropdownListsElementClick(){console.log("Now'this'refers to the MyListItem itself")}}//end of the class

Related

`this` inside inner functions [duplicate]

I have a question concerning how the "this" pointer is treated in a nested function scenario.
Say I insert this following sample code into a web page. I get an error when I call the nested function "doSomeEffects()". I checked in Firebug and it indicates that when I am in that nested function, the "this" pointer is actually pointing to the global "window" object - which I did not expect. I must not be understanding something correctly because I thought since I declared the nested function within a function of the object, it should have "local" scope in relation to the function (i.e. the "this" pointer would be referring to the object itself like how it is in my first "if" statement).
Any pointers (no pun intended) would be appreciated.
var std_obj = {
options : { rows: 0, cols: 0 },
activeEffect : "none",
displayMe : function() {
// the 'this' pointer is referring to the std_obj
if (this.activeEffect=="fade") { }
var doSomeEffects = function() {
// the 'this' pointer is referring to the window obj, why?
if (this.activeEffect=="fade") { }
}
doSomeEffects();
}
};
std_obj.displayMe();
In JavaScript the this object is really based on how you make your function calls.
In general there are three ways to setup the this object:
someThing.someFunction(arg1, arg2, argN)
someFunction.call(someThing, arg1, arg2, argN)
someFunction.apply(someThing, [arg1, arg2, argN])
In all of the above examples the this object will be someThing.
Calling a function without a leading parent object will generally get you the global object which in most browsers means the window object.
Since this appears to be among the most upvoted questions of its kind, let me add, after all these years, the ES6 solution using arrow functions:
var std_obj = {
...
displayMe() {
...
var doSomeEffects = () => {
^^^^^^^ ARROW FUNCTION
// In an arrow function, the 'this' pointer is interpreted lexically,
// so it will refer to the object as desired.
if (this.activeEffect=="fade") { }
};
...
}
};
this is not part of the closure scope, it can be thought of as an additional parameter to the function that is bound at the call site. If the method is not called as a method then the global object is passed as this. In the browser, the global object is identical to window. For example, consider the following funciton,
function someFunction() {
}
and the following object,
var obj = { someFunction: someFunction };
If you call the function using method syntax such as,
obj.someFunciton();
then this is bound to obj.
If you call someFunction() directly, such as,
someFunction();
then this is bound to the global object, that is window.
The most common work around is to capture this into the closure such as,
displayMe : function() {
// the 'this' pointer is referring to the std_obj
if (this.activeEffect=="fade") { }
var that = this;
var doSomeEffects = function() {
// the 'this' pointer is referring to global
// that, however, refers to the outscope this
if (that.activeEffect=="fade") { }
}
doSomeEffects();
}
To understand this question , try to get the output for the following snippet
var myObject = {
foo: "bar",
func: function() {
var self = this;
console.log("outer func: this.foo = " + this.foo);
console.log("outer func: self.foo = " + self.foo);
(function() {
console.log("inner func: this.foo = " + this.foo);
console.log("inner func: self.foo = " + self.foo);
}());
}
};
myObject.func();
The above code will output the following to the console:
outer func: this.foo = bar
outer func: self.foo = bar
inner func: this.foo = undefined
inner func: self.foo = bar
In the outer function, both this and self refer to myObject and therefore both can properly reference and access foo.
In the inner function, though, this no longer refers to myObject. As a result, this.foo is undefined in the inner function, whereas the reference to the local variable self remains in scope and is accessible there. (Prior to ECMA 5, this in the inner function would refer to the global window object; whereas, as of ECMA 5, this in the inner function would be undefined.)
There's a difference between enclosure variables and "this". "this" is actually defined by the invoker of the function, while explicit variables remain intact inside the function declaration block known as the enclosure. See the example below:
function myFirstObject(){
var _this = this;
this.name = "myFirstObject";
this.getName = function(){
console.log("_this.name = " + _this.name + " this.name = " + this.name);
}
}
function mySecondObject(){
var _this = this;
this.name = "mySecondObject";
var firstObject = new myFirstObject();
this.getName = firstObject.getName
}
var secondObject = new mySecondObject();
secondObject.getName();
you can try it out here:
http://jsfiddle.net/kSTBy/
What's happening in your function is "doSomeEffects()", is being called explicitly, this means context or the "this" of the function is the window. if "doSomeEffects" was a prototype method e.g. this.doSomeEffects on say "myObject", then myObject.doSomeEffects() would cause "this" to be "myObject".
As explained by Kyle, you could use call or apply to specify this within the function:
Here is that concept applied to your code:
var std_obj = {
options: {
rows: 0,
cols: 0
},
activeEffect: "none",
displayMe: function() {
// the 'this' pointer is referring to the std_obj
if (this.activeEffect == "fade") {}
var doSomeEffects = function() {
// the 'this' pointer is referring to the window obj, why?
if (this.activeEffect == "fade") {}
}
doSomeEffects.apply(this,[]);
}
};
std_obj.displayMe();
JsFiddle
Since it wasn't mentioned I will mention that using .bind() is a solution -
doSomeEffects=doSomeEffect.bind(this);
doSomeEffects();
}
};
std_obj.displayMe();
Here is a more simple example -
bad = {
name:'NAME',
z : function() {
function x() { console.log(this.name); };
x()
}
};
bad.z() // prints 'undefined'
good = {
name:'NAME',
z : function() {
function x() { console.log(this.name); };
x=x.bind(this);
x();
}
};
good.z() // prints 'NAME'
It is true that using an arrow function => looks slicker and is easy for the programmer. However, it should be kept in mind that a lexical scope is likely to require more work in terms of processing and memory to setup and maintain that lexical scope, compared to simply associating a function's this with a pointer via .bind().
Part of the benefit of developing classes in JS was to provide a method to make this more reliably present and available, to pivot away from functional programming and lexical scopes, and thus reduce overhead.
From MDN
Performance considerations
It is unwise to unnecessarily create functions within other functions if closures are not needed for a particular task, as it will negatively affect script performance both in terms of processing speed and memory consumption.
It's because "this" refers to the self object / local function.
var std_obj = {
options : { rows: 0, cols: 0 },
activeEffect : "none",
displayMe : function() {
if (this.activeEffect=="fade") { }
let This = this; // 'this' here is for the std_obj scope. Create a reference to 'this' if you want to use it elsewhere.
var doSomeEffects = function() {
// 'this' here refers to the doSomeEffects scope. If you don't want "this," you can still use "this" of the std_obj scope.
if (This.activeEffect=="fade") { }
}
doSomeEffects();
}
};
std_obj.displayMe();
I also got a warning "Potentially invalid reference access to a class field via this"
class MyListItem {
constructor(labelPrm) {
this._flagActive = false;
this._myLabel = labelPrm;
labelPrm.addEventListener('click', ()=>{ this.onDropdownListsElementClick();}, false);
}
get myLabel() {
return this._myLabel
}
get flagActive(){
return this._flagActive;
}
onDropdownListsElementClick(){console.log("Now'this'refers to the MyListItem itself")}}//end of the class

Access current element's 'this' object when an external 'this' was bind

Don't know if the question's title is too confusing but here I go.
If I got something like:
var Test = function(){
this.foo = a;
}
Test.prototype.init = function() {
$(document).on('change', '.form-control', this.myFunction);
}
Test.prototype.myFunction = function() {
console.log(this.foo);
console.log(this);
}
My understanding is that when printing 'this' in myFunction it would print the execution context of the function that made the call, in this case it'll print the execution context for .on('change' ...). So when printing this.foo since it doesn't exist in that context then undefined will be printed out.
To solve this issue and to access this.foo, I'm doing the following:
Test.prototype.init = function() {
$(document).on('change', '.form-control', (this.myFunction).bind(this));
}
Test.prototype.myFunction = function() {
console.log(this.foo);
console.log(this);
}
I'm binding 'this' to the function call, so this.foo would be printed out which is OK, but my question is, in that case how can I also get access to the execution context for .on('change' ...)??? Meaning, how can I access the 'this' that I had originally access to before the binding?
Thanks
Instead of binding, just use a reference variable. It will maintain the context, and still allow you to use the .on's context with this
Test.prototype.init = function () {
var context = this;
$(document).on('change', '.form-control', function () {
context.myFunction();
console.log(this); // `this` has context to the onchange
});
};
A bound function's this will always be bound to that same value. That means you no longer have access to the "original" value.
If you want to use both thises, you'll have to use one as this and the other as an argument. Or both as arguments.
var Test = function(a) {
this.foo = a;
this.init();
}
Test.prototype.init = function() {
// Set `this` to the calling test object, and window
// (which would be the original context in this case)
// as first parameter of `myFunction`. Swap the arguments
// if you wish to use them the other way around.
window.setTimeout(this.myFunction.bind(this, window), 500);
};
Test.prototype.myFunction = function(that) {
console.log(this.foo);
console.log(that.foo);
};
new Test(5);
Btw, ES6 arrow functions keep the environment they're defined in, meaning that this would point to your test object.
Test.prototype.init = function() {
window.setTimeout(() => this.myFunction(window), 500);
};

Javascript nested function losing scope

Can someone explains the scope binding of the following code please
window.name = "window";
object = {
name: "object",
method: function() {
nestedMethod: function() {
console.log(this.name);
}
nestedMethod();
}
}
object.method(); // print 'window'
I think my question is more about this...why is this losing the scope and default to the global scope ? do all the anonymous functions that we created will go on the global scope ?
Whenever you call a function, simply by writing func(), this inside the function will point to the global object. In your case you write:
nestedMethod();
So this inside nestedMethod is the window object. You can use call (or apply) to manually define a context for you function call:
nestedMethod.call(this);
Any function that's invoked like this:
someFunction();
will have the global scope as the value of this (in non-strict mode). You can either stash the outer scope in a local variable, or else use .call() or .apply():
nestedMethod.call(this);
window.name = "window";
object = {
name: "object",
method: function () {
var self = this;
var nestedMethod = function () {
console.log(self.name); // or object.name without declaring self
}
nestedMethod();
}
}
object.method(); // print 'object'
Save the scope of the object - or use the object itself!
do all the anonymous functions that we created will go on the global scope ?
No, not all the anonymous functions lose their scope, all the functions scopes are bound to the global object(if they are not called with specific this, see apply and call, see the example below)!
window.name = "window";
object = {
name: "object",
method: function () {
var nestedMethod = function () {
console.log(this.name);
}
nestedMethod.call(this); //change the this arg in the current object scope
// when you call this function with .call(this) you are changing the value of the nestedMethod's this to the current this, which is object
}
}
object.method(); // print 'object'
you should declare nested function like this:
Super.prototype.someFunc = function() {
this.nestedFunc = function() {}
//now call it
this.nestedFunc()
}

This pointer from internal function

i have JavaScript components, that has following architecture:
var MyComponent = function(params)
{
setup(params);
this.doSomething()
{
// doing something
};
function setup(params)
{
// Setup
// Interaction logic
var _this = this; // "this" points to DOMWindow, not to created object
$(".some-element").click(function(){
_this.doSomething(); // it craches here, because of above
});
}
};
When something, being controlled by interaction logic, happens, sometimes i must forward execution to "public" methods of component.
In this situation, i have a problem with "this" pointer.
Sample code demonstrates it:
var Item = function()
{
this.say = function()
{
alert("hello");
};
this.sayInternal = function()
{
_sayInternal();
};
function _sayInternal()
{
this.say();
};
};
To test it,
Create an object:
var o = new Item();
This works fine:
o.say(); // alerts "hello"
This crashes:
o.sayInternal();
I get an error:
TypeError: Result of expression 'this.say' [undefined] is not a function.
I think, such a behaviour takes place, because _sayInternal() function is declared (and not assigned to object, like "this.say = function()"). This way, it is shared across all created objects and acts like a static function in C++.
Is this true ?
No, sayInternal is not shared between created objects. But you are right, the created objects don't have access to sayInternal as it is not assigned to them. This function is only local to the constructor function.
this always refers to the context a function is invoked in. If you call it like func(), then this refers to the global object (which is window in browser). If you set the function as property of an object and call it with obj.func(), then this will refer to obj.
If you assign a "bound" function to a variable and call it:
var method = obj.func;
method();
then this will again refer to the global object. In JavaScript, functions are like any other value, they don't have a special relationship to the object they are assigned to.
You can explicitly set the context with call or apply:
var MyComponent = function(params)
{
setup.call(this, params); // <- using `call`
this.doSomething()
{
// doing something
};
function setup(params)
{
// Setup
// Interaction logic
var _this = this; // "this" to new created object
$(".some-element").click(function(){
_this.doSomething();
});
}
};
or in you other example:
var Item = function()
{
this.say = function()
{
alert("hello");
};
this.sayInternal = function()
{
_sayInternal.call(this);
};
function _sayInternal()
{
this.say();
};
};
That said, this approach to assign functions to objects is not good, because every instance will have its own this.sayInternal function. So for the Item code above, every creation of an instance involves creating three functions too, which is a waste of memory.
Making use of prototype inheritance would be a better way:
var Item = function() {
};
Item.prototype = (function() {
function _sayInternal() {
this.say();
};
return {
say: function() {
alert("hello");
},
sayInternal: function(){
_sayInternal.call(this);
}
}
}());
This way, _sayInternal is only created once and all instances inherit (refer to) the prototype, so say and sayInternal also exist only once. The "trick" with the immediate function makes _sayInternal only accessible by say and sayInternal.

'this' in function inside prototype function [duplicate]

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 4 years ago.
I basically have an object, extended with a function through its prototype. Inside that function, another function exists, however when using this in this nested function, it does not seem to refer to the object, but the function.
For example,
var sampleObject = function() {
this.foo = 123;
}
sampleObject.prototype.getFoo = function() {
var nested = function() {
return this.foo;
}
return nested();
}
var test = new sampleObject();
window.alert(test.getFoo()); // undefined
The this.foo does not refer to the 123 value, but is undefined as this refers to the nested function, in which no foo exists. How can I access the 123 value from the nested function?
sampleObject.prototype.getFoo = function() {
var me = this;
var nested = function() {
return me.foo;
}
return nested;
}
By saving the value of this in a local variable, you make it explicitly part of the lexical context for that function and for all nested function scopes. Thus, on the call to "nested", that inner function will have its own scope (it's own this value), but it can still refer to the variable "me" in the enclosing scope.
In your example "this" refers to the window object because you didn't specify another context when you call the nested function and you get undefind because window.foo is undefined.
You can fix this in 3 ways.
1 - Use a variable to store the outside this - most used method
sampleObject.prototype.getFoo = function() {
var _this = this;
var nested = function() {
return _this.foo;
}
return nested();
}
2 - Use the bind method which bind the outer "this" to the inner one
sampleObject.prototype.getFoo = function() {
var nested = function() {
return this.foo;
}.bind(this);
return nested();
}
3 - Use the call method which can pass the context to the function
SampleObject.prototype.getFoo = function() {
var nested = function() {
return this.foo;
};
return nested.call(this);
}
The common work around for that is to use closure
sampleObject.prototype.getFoo = function() {
var _this = this;
var nested = function() {
return _this.foo;
}
return nested();
}
Some libraries add methods to automate this
Prototype adds Function.bind (http://prototypejs.org/doc/latest/language/Function/prototype/bind/)
Ext adds function.createDelegate (http://www.sencha.com/learn/Manual:Utilities:Function#createDelegate)
Javascript 1.8.5 adds function.bind (https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind)
tl;dr
Use arrow functions. They are available since ECMAScript 6:
var sampleObject = function() {
this.foo = 123;
}
sampleObject.prototype.getFoo = function() {
var nested = () => { // Changed this line.
return this.foo;
}
return nested();
}
var test = new sampleObject();
window.alert(test.getFoo());
Explanation
This is one of the main advantages of arrow functions. Your case is described in the section: No binding of this. The refference states:
Until arrow functions, every new function defined its own this value [...]
An arrow function does not create its own this context, so this has the original meaning from the enclosing context.
Apart from declaring it to var _this = this, I also see codes doing var that = this or var self = this.
Knowing your variable's scope is important as it might raises unexpected result.
This is an old question, but I give another solution for the sake of completeness. Another approach involves function binding.
sampleObject.prototype.getFoo = function() {
var nested = function() {
return this.foo;
}
return nested.bind(this)();
}
An ES6 way of doing this would be to use an Arrow Function. Basically, when you use an arrow function, it does not create it's own "this" context. So, using "this" would then refer to the parent function's context. Here's how the code would look:
sampleObject.prototype.getFoo = function() {
const nested = () => {
return this.foo; //"this" refers to parent function's context
}
return nested;
}
This is a known wart on JavaScript. The usual pattern is to assign this to another variable (often self) in the outer function, then access self from the inner funtction. This works.

Categories