Javascript nested function losing scope - javascript

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()
}

Related

Javascript - why is this referring to global window if I pass an arrow function as callback vs defined same func inside the callback handler?

Why is the value of this in first example: this: myObject and document/window in the second example? If this is defined/evaluated when the function is called, then I dont understand it.
myObject = {
myMethod: function () {
helperObject.doSomethingAsync('superCool', () => {
console.log(this); // this === myObject
});
},
};
const reusabledCallback = () => {
console.log(this); // this === window or global object
};
myObject = {
myMethod: function () {
helperObject.doSomethingAsync('superCool', reusabledCallback);
},
};
this in an arrow function is the same this as the one in the outer scope where the function is defined.
this in a function declared with the keyword function is the object on which the function is being called.
this in the global scope is the window object (or the relevant global object)
In your first code, the arrow function containing this is defined inside a function, so this is whatever called that function (myObject in your case).
In your second code, the arrow function containing this is defined in the global scope, so this is the global object (window).

How to pass down function with "this" keyword [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

`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

Why the property of this cannot be accessed directlly within a private function in a closure?

In my own answer for A JavaScript VM that interprets code written in JSON I stated that the "public" properties of a JavaScript closure cannot be accessed in a "private" function.
The example given in that post is
function anobject(){
var privatefunction = function(){
//publicfunction(); //wrong; you have no access to it
console.log(this); //refer to the global object, not the object creating
};
this.publicfunction = function(){
console.log(this); //refer to the object creating
}
}
I think the reason is for some backward compatibility issues privatefunction must belong to the global object. So the public function is only an anonymous function that assigned to a property of this. This explains why calling publicfunction will fail because it need to have a reference to this first.
However, the following fix is still not work:
function anobject(){
var privatefunction = function(){
//publicfunction(); //wrong; you have no access to it
console.log(this); //refer to the object creating
}.bind(this);
this.publicfunction = function(){
console.log(this); //refer to the object creating
}
}
As I explicitly specify that privatefunction should be bound with the object creating, calling publicfunction should work but it does not. I have to do the following:
function anobject(){
var privatefunction = function(){
this.publicfunction();
console.log(this); //refer to the object creating
}.bind(this);
this.publicfunction = function(){
console.log(this); //refer to the object creating
}
}
Another workaround (the way that I am using) is the following:
function anobject(){
var privatefunction = function(){
publicfunction();
console.log(this); //refer to the object creating
};
var publicfunction = function(){
console.log(this); //refer to the object creating
}
this.publicfunction = publicfunction;
}
Now is the question part. What is the reason behind this behavior? What is it trying to avoid by disabling access this's properties without explicit specification?
UPDATE: the main part of the question is : When the interpreter cannot find a name in the scope chains, why should'nt it have a look at the this properties?
The problem here is that the reference this is determined by the caller of the function/method, for example:
function anobject(){
// here "this" is the object
var privatefunction = function(){
// here "this" is the object **that called privatefunction()**
};
this.publicfunction = function(){
// this method will always be called by the object, so "this" is the object
}
}
To achieve what you want you could also try this:
function anobject(){
var that = this;
var privatefunction = function(){
[do what you like using "that"]
};
this.publicfunction = function(){
[here you can use "this" directly, or "that"]
}
}
See also how javascript scope works, here What is the scope of variables in JavaScript? and on the web.
In the second example, publicfunction() is delcared as a property of the object this:
this.publicfunction = function(){
console.log(this);
}
Therefore, this function is not directly accessible by its name publicfunction(), and that is independent of the context. The function does not actually belong to any context, but rather to the object of which it is a property.
In your example, when privatefunction() calls publicfunction(), this raises an error because there is no function declared as a variable with the name publicfunction(), and not because this's properties are not accessible:
function anobject(){
var privatefunction = function(){
//publicfunction(); // You cannot call publicfunction() because there is
// no function defined with this name
}.bind(this);
this.publicfunction = function(){
console.log(this);
}
}
Look at this example, publicfunction() is not accessible even within anobject():
function anobject(){
this.publicfunction = function() {
console.log(this);
}
// publicfunction(); // Wrong because publicfunction()
// was not defined as a variable
}
However, if publicfunction() was defined as a variable within the context of anobject(), then this function would be accessible by its name. For example you can simply declare function publicfunction() within the closure of anobject():
function anobject(){
function publicfunction() {
console.log(this);
}
publicfunction(); // You can access publicfunction() here
}
But in this case, publicfunction() is not accessible outside the execution context of anobject(), therefore it can be regarded as a 'private' function:
var a = new anobject();
if(typeof a.publicfunction === 'undefined')
console.log('Public function is undefined outside of anobject()');
As a result, that's why we use the this keyword to declare publicfunction(): it makes it accessible outside the context of anobject(), but doing so define this function only as a property of anobject().
Therefore the only way to access this function is by calling this.publicfunction():
function anobject(){
var privatefunction = function(){
this.publicfunction();
console.log(this);
}.bind(this);
this.publicfunction = function(){
console.log(this);
}
}
More details regarding the this keyword: How does "this" keyword work within a function?
Variable vs. Properties in JavaScript: http://javascriptweblog.wordpress.com/2010/08/09/variables-vs-properties-in-javascript/

OOP. Calling methods from within methods

How do I call class methods from functions within the class? My code is:
var myExtension = {
init: function() {
// Call onPageLoad
},
onPageLoad: function() {
// Do something
},
}
I've tried ...
onPageLoad();
... from within the init method but it's saying it's not defined.
I'm not having much luck with google because I don't understand the syntax used. All the JS OOP examples I find online are in a different format. I'm using the format Mozilla use for extension development.
The object the current method was invoked on is available via the special variable this. Any time you call a method on an object, this will refer, within the method, to the object.
var myExtension = {
init: function() {
this.onPageLoad();
},
onPageLoad: function() {
// Do something
},
};
this always refers to the calling object rather than the object the function is defined on or is a property of.
value = 'global';
var ob0 = {
value: 'foo',
val: function() {
return this.value;
},
},
ob1 = {value: 'bar'},
ob2 = {value: 'baz'};
ob0.val(); // 'foo'
ob1.val = ob0.foo;
ob1.val(); // 'bar'
ob0.val.call(ob2); // 'baz'
var val = ob0.val;
val(); // 'global'
In the last case, val is executed as a free function (a function that isn't bound to an object, i.e. not a method), in which case this takes on the value of the global object (which is window in web browsers) within the execution of val. Global variables are actually properties of the global object, hence val() returns 'global' (the value of the global variable named value). Since global variables are actually properties of the global object, you can view free functions as actually being methods of the global object. From this viewpoint, the last two lines (when executed in global scope) are equivalent to:
window.val = ob0.val;
window.val();
This viewpoint doesn't exactly match the reality of scoping, though you'll only notice the difference within functions. In a function, window.val = ... will create a global while var val won't.
value = 'global';
var ob0 = {
value: 'foo',
val: function() {
return this.value;
},
};
function lcl() {
var val = ob0.val; // doesn't set a global named `val`
return val(); // 'global'
}
lcl(); // 'global'
val(); // error; nothing named 'val'
function glbl() {
window.val = ob0.val; // sets a global named `val`
return window.val(); // 'global'
}
glbl(); // 'global'
val(); // 'global'
See MDN's reference page for more on the call method used above. For more on the this variable, see "JavaScript “this” keyword" and "How does “this” keyword work within a JavaScript object literal?"
Assuming that you have called init like this:
myExtension.init();
then it should be:
init: function() {
// before
this.onPageLoad();
// after
}
But in Javascript functions are not actually bound to objects and you can call any function on any other object, like this:
myExtension.init.call(anotherObject); // or
myExtension.init.apply(anotherObject);
In this example this within init would be anotherObject, which doesn't have onPageLoad defined. If you want to support this kind of usage you'll have to manually reference the initial object:
init: function() {
// before
myExtension.onPageLoad();
// after
}
In Javascript you need to explicitly mention the this
this.onPageLoad()
The same is also true for other member variables (remember that in Javascript methods are just member variables that happen to be functions)
this.memberVariable
Have you considered a closure, instead?
For example:
var myExtension = ( function() {
var me = {};
var private_thingy = "abcDEFG123";
var onPageLoad = function() {
// do page loading business
alert( private_thingy );
}
me.onPageLoad = onPageLoad;
var init = function() {
onPageLoad();
}
me.init = init;
return me;
})();
///////////////
myExtension.private_thingy = "DIDDLED!";
// will NOT modify the private_thingy declared within the closure
myExtension.init(); // will work fine.
Anything you define within the closure is available within the closure at all times, and when implemented carefully will yield private members not accessible to users of the object. Only members that you explicitly export - e.g., the me.xxx = xxx lines - are publicly available.
Thus, when onPageLoad executes, "abcDEFG123" will be displayed in the alert, not "DIDDLED!". Users of the object can modify properties using the dot operator until the cows come home; what's not made public by the closure, however, can never be modified: even if the user reassigns a function on the public interface, calls to the private function from within the closure will always point to the function defined within the closure.
The important part: it unties you from the constant use of this (unless you really want to use it; save your fingers for more important typing!).
Give it a shot. And have a look at Javascript: The Good Parts by Crockford.

Categories