Function object, context and this [duplicate] - javascript

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
this operator in javascript
The term context is bit confusing me.If i declare a function within a function i.e nested function and execute there itself,like below...
function foo(){
function fo(){
alert(this);
}
fo();
}
the this keyword should point to the function object rather than window since function fo() is within its parent function.Since function is also an javascript object,than why the this keyword is traversing the function object and pointing to window?
Also this keyword points to the current object on which the function operates ,so function object is the object on which the nested function operates.

If you just call foo() in the top level, it is identical to window.foo().
And window is the actual context of foo, so, this points to the window object.

Adding to what dlutxx said. If you have a function (in the global space) and you simply call it like foo() the context is the window itself (since the function is a member of the window object). However, if you use the new keyword for getting a new instance of the function, this will refer to the function object.
function foo() {
alert(this);
}
foo(); // "this" inside the function will be window
new foo(); // "this" inside the function will be the function object.
If you want to have a custom value for this inside the function, you can call it using .call() like:
foo.call(x); // "this" inside the function will be x
Example code for your case:
function foo(){
function fo(){
alert(this);
}
fo(); // "this" is window
new fo(); // "this" is the function object
fo.call('x'); // "this" is 'x'
}

If you randomly use this inside of a function which is NOT a constructor, then you will get one of a few different results:
function callThis () { return this; }
callThis(); // returns window object
var Bob = { func : callThis };
Bob.func(); // returns Bob
callThis.call(Bob); // returns Bob
Call is a method which is used to determine the context of the call.
If the call's context can not be determined by:
a. What's in front of the "." (Bob.func();)
b. What's explicitly passed into .call(), .apply() or .bind()
Then it's set to window.
That is how context is resolved.
So if you have a specific object in mind for this, then your solutions are as follows:
function objMethod () {
var self = this;
function doStuff () {
self.otherFunc();
self.otherProperty = "bob";
}
doStuff();
}
var myObj = { myMethod : objMethod };
myObj.myMethod();
myObj calls objMethod with the context set to myObj.
objMethod saves a reference to the current context (myObj) as self. doStuff uses the reference to modify the properties of the referenced object.
function outer () {
function inner () { this.property = "Bob"; }
inner.call(this);
}
var obj = {};
outer.call(obj);
Here, outer is passed a context, using .call().
Then inner is passed the this of outer, again, using .call()
var bob = { name : "Bob" };
function sayName () { console.log(this.name); }
var bobFunc = sayName.bind(bob);
bobFunc();
Here, we use .bind() to create a version of sayName where this is always set to bob.
You can feel free to mix and match these systems all you'd like (and when dealing with async programming, you likely will).

my understanding is that although function fo() is defined in the scope of function foo(), which means that it is not accessible from outside of foo unless you return it, the rules that apply to the value of this when you call this internal function, are still the same as if you called any other function.
function f() {
function g() {
console.log(this)
}
console.log(this);
g();
g.apply(this);
}
f() // => Window, Window, Window
f.apply(this) // => Window, Window, Window
f.apply({}) // => Object, Window, Object

Related

Why is `this` in nested function the window object when I set the context with the `.call` method? [duplicate]

This question already has answers here:
How does the "this" keyword work, and when should it be used?
(22 answers)
Closed 1 year ago.
I do not understand why the this value is the window object when I set the context for the f6 function to run with the object obj.
let obj = {
color: "blue",
name: "maya"
};
function f6() {
return function() {
console.log(this);
}
}
f6.call(obj)();
In function functions, this is not determined by lexical scope.
It’s determined by how the function is called, and in what context.
Each function function creates its own this binding environment.
function f(){
this; // This `this` is distinct …
function g(){
this; // … from this `this`.
}
}
function f(){
console.log(this);
}
const objX = {
f
},
objY = {};
objX.f(); // Logs `objX`, because the expression `objX.f` is a member of a reference.
f(); // No `this` binding. `f` by itself isn’t the member of a reference.
f.call(objY); // Logs `objY`, because `this` was explicitly set.
Arrow functions, on the other hand, get the this binding from their lexical scope.
Arrow functions do not create their own this binding environment.
function f(){
this; // This `this` is the same …
() => {
this; // … as this `this`.
};
}
You’re calling f6 with .call to provide a this binding.
That’s where the f6 function gets its this value from, but f6 doesn’t use its this value.
Unrelatedly, f6 returns a function that happens to use this.
Again, it’s a function function, so its this binding depends on the call.
If you’re wondering what the returned function’s this value will be, you’ll have to examine the call:
f6.call(obj)();
// Equivalent to:
(f6.call(obj)) ();
// -^^^^^^^^^^^^- Returned function.
// ^^ Call.
.call or .apply isn’t used on the returned function, and .bind wasn’t used, so the this binding isn’t set explicitly.
(f6.call(obj)) also isn’t an expression with a member of a reference (i.e. a MemberExpression).
The call was performed without providing a context, so the context will be globalThis, or undefined in strict mode.
Using an arrow function resolves this:
function f6(){
return () => console.log(this);
}
f6.call(obj)(); // Logs `obj`.
Alternatively, using .bind in the return would also resolve this:
function f6(){
return function(){
console.log(this);
}.bind(this);
}
f6.call(obj)(); // Logs `obj`.
And of course, using something that is lexically scoped1, i.e. variables, would also resolve this:
function f6(){
const that = this;
return function(){
console.log(that);
};
}
f6.call(obj)(); // Logs `obj`.
1: I guess you could say that this is also lexically scoped, but is overshadowed by each nested function function.
See also:
ECMAScript specification on function calls
ECMAScript specification on the this keyword
Stack Overflow: How does the “this” keyword work?

Understanding `this` behaviour where `arguments` are involved [duplicate]

This question already has answers here:
How does the "this" keyword work, and when should it be used?
(22 answers)
Closed 4 years ago.
So, I have 3 functions as follows:
function a() {
arguments[0]();
}
function b(fn) {
fn();
}
function c() {
console.log(this);
}
Now, consider the outputs:
a(c) // Arguments
b(c) // Window
a(() => {console.log(this}) // Window
b(() => {console.log(this)}) // Window
Why does a(c) output Arguments while it is window (considering non-strict) in all other cases?
In JavaScript this usually refers to the object from which the function was called (unless it's an arrow function). So for example if we do something like this:
var obj = { fun: function() { console.log(this); } }
var obj1 = { fun: obj.fun, otherProperty: 123 }
obj.fun(); // equivalent to obj["fun"]()
obj1.fun(); // equivalent to obj1["fun"]()
We will find out that in the first call this refers to obj and in the second it refers to obj1 even though it's the same function.
Now, the arguments variable is an object which stores all the arguments which were passed to the function. If an argument was a function and you access it through the arguments object, it becomes a "parent" object from which the function was called and it becomes the new this in the function's execution context. You can consider your case to be equal to something like this:
function c() {
console.log(this);
}
var arguments = { "0" : c }
arguments["0"]() // will log the arguments object
In your second invocation (b(c)) the function passed as an argument is called directly inside the parent function, without accessing it through a proxy object - in that case this will be copied from the parent execution scope, which is window.
In the third and fourth example both functions are defined using the arrow function, which saves the value of this from the context in which they were created and they prevent this value from being changed.
More about arrow functions: Arrow functions

this context bug in javascript - why doesn't this trigger a bug?

I thought this was suppose to trigger a bug when calling a function from within a function using the keyword this. Running Chrome 37.0
S = function () {
this.x = "test";
this.test1 = function () {
console.log("test1");
this.test2();
};
this.test2 = function () {
console.log(this); // output is s object, thought 'this' suppose to be global?
console.log("test2");
};
};
s = new S();
s.test1();
Edit:
I mixed it up with this code:
s = function () {
console.log(this);
var t = function () {
console.log(this);
};
t();
};
x = new s();
Calling a function as part of an expression where you get the function reference from an object property calls the function with this set to the object you got the property from.
So your code:
s.test1();
...will call test1 setting this equal to the object referenced by s, because the call is part of an expression getting the test1 function reference from a property on the object s refers to.
Then in test1, when you do:
this.test2();
...it calls test2 setting this equal to the object referenced by this, because the call is part of an expression getting the test2 function reference from a property on the object this refers to.
Where you'd run into a problem with this not being set correctly would be if you didn't call test1 or test2 via an object property, like this:
var f = s.test1;
f();
Then, within the call to test1, this would be the global object (in loose mode) or undefined (in strict mode). The same sort of thing happens when passing a function as an argument:
foo(s.test1);
If foo calls the function its first argument relates to, we get the same thing (this = global object or undefined).
Since you're not doing that, though, that doesn't happen.
The key thing here is how the function is called, not where it's defined (inside another function or not).
More on this in How Does The this Keyword Work? here on SO, and in Mythical methods and You must remember this on my blog.

Javascript: why "this" inside the private function refers to the global scope?

Consider the following code:
function A() {}
A.prototype.go = function() {
console.log(this); //A { go=function()}
var f = function() {
console.log(this); //Window
};
f();
}
var a = new A();
a.go();
Why does 'this' inside function 'f' refers to the global scope? Why it is not the scope of function 'A' ?
JavaScript has a different concept of what the special name this refers to
than most other programming languages do. There are exactly five different
ways in which the value of this can be bound in the language.
The Global Scope
this;
When using this in global scope, it will simply refer to the global object.
Calling a Function
foo();
Here, this will again refer to the global object.
ES5 Note: In strict mode, the global case no longer exists.
this will instead have the value of undefined in that case.
Calling a Method
test.foo();
In this example, this will refer to test.
Calling a Constructor
new foo();
A function call that is preceded by the new keyword acts as
a constructor. Inside the function, this will refer
to a newly created Object.
Explicit Setting of this
function foo(a, b, c) {}
var bar = {};
foo.apply(bar, [1, 2, 3]); // array will expand to the below
foo.call(bar, 1, 2, 3); // results in a = 1, b = 2, c = 3
When using the call or apply methods of Function.prototype, the value of
this inside the called function gets explicitly set to the first argument
of the corresponding function call.
As a result, in the above example the method case does not apply, and this
inside of foo will be set to bar.
Note: this cannot be used to refer to the object inside of an Object
literal. So var obj = {me: this} will not result in me referring to
obj, since this only gets bound by one of the five listed cases.
Common Pitfalls
While most of these cases make sense, the first one is to be considered another
mis-design of the language because it never has any practical use.
Foo.method = function() {
function test() {
// this is set to the global object
}
test();
}
A common misconception is that this inside of test refers to Foo; while in
fact, it does not.
In order to gain access to Foo from within test, it is necessary to create a
local variable inside of method which refers to Foo.
Foo.method = function() {
var that = this;
function test() {
// Use that instead of this here
}
test();
}
that is just a normal variable name, but it is commonly used for the reference to an
outer this. In combination with closures, it can also
be used to pass this values around.
Assigning Methods
Another thing that does not work in JavaScript is function aliasing, which is
assigning a method to a variable.
var test = someObject.methodTest;
test();
Due to the first case, test now acts like a plain function call; therefore,
this inside it will no longer refer to someObject.
While the late binding of this might seem like a bad idea at first, in
fact, it is what makes prototypal inheritance work.
function Foo() {}
Foo.prototype.method = function() {};
function Bar() {}
Bar.prototype = Foo.prototype;
new Bar().method();
When method gets called on a instance of Bar, this will now refer to that
very instance.
Disclaimer: Shamelessy stolen from my own resources at http://bonsaiden.github.com/JavaScript-Garden/#function.this
The reason why is you are invoking f as a function and not a method. When invoked as a function this is set to window during the execution of the target
// Method invocation. Invoking a member (go) of an object (a). Hence
// inside "go" this === a
a.go();
// Function invocation. Invoking a function directly and not as a member
// of an object. Hence inside "f" this === window
f();
// Function invocation.
var example = a.go;
example();
The scope of all functions is window.
To circumvent that, you can do this:
function A() {}
A.prototype.go = function() {
var self = this;
console.log(self); //A { go=function()}
var f = function() {
console.log(self); //A { go=function()}
};
f();
}
Because function f() is not called without any object reference. Try,
f.apply(this);

this value in JavaScript anonymous function

Can anybody explain to me why A is true and B is false? I would have expected B to be true as well.
function MyObject() {
};
MyObject.prototype.test = function () {
console.log("A", this instanceof MyObject);
(function () {
console.log("B", this instanceof MyObject);
}());
}
new MyObject().test();
update:
since ecmascript-6 you can use arrow functions which would make it easy to refer to MyObject like this:
function MyObject() {
};
MyObject.prototype.test = function () {
console.log("A", this instanceof MyObject);
(() => {//a change is here, which will have the effect of the next line resulting in true
console.log("B", this instanceof MyObject);
})(); //and here is a change
}
new MyObject().test();
Inside of your anonymous function this is the global object.
Inside of test, this is the instance of MyObject on which the method was invoked.
Whenever you call a function like this:
someFunction(); // called function invocation
this is always the global object, or undefined in strict mode (unless someFunction was created with bind** — see below)
Whenever you call a function like this
foo.someMethod(); //called method invocation
this is set to foo
**EcmaScript5 defines a bind function that allows you to create a function that has a pre-set value for this
So this
var obj = { a: 12 };
var someFunction = (function () { alert(this.a); }).bind(obj);
someFunction();
Causes someFucntion to be invoked with this equal to obj, and alerts 12. I bring this up only to note that this is a potential exception to the rule I mentioned about functions invoked as
someFunction();
always having this equal to the global object (or undefined in strict mode)
this is special. It refers to the object that the function is being called on behalf of (most commonly via dot syntax).
So, in the case of A, the function is being called on behalf of a new MyObject object. B is in a different function that isn't explicitly being called on behalf of any object, so this defaults to the global object (window).
In other words, this changes depending on how the function is called, not where or how it is defined. The fact that you're using an anonymous function (defined inside another function) is coincidental and has no effect on the value of this.
In the anonymous function, this is bound to the global object (window in a browser environment).
There are various ways of accessing the instance:
var self = this;
(function () {
console.log("B", self instanceof MyObject);
}());
or
(function () {
console.log("B", this instanceof MyObject);
}).call(this);
this is set based on how you call the function.
Your anonymous function is a normal function call, so this is the global object.
You could write (function() { ... }).call(this) to explicitly call it with your this.

Categories

Resources