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

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

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?

'this' key word inside arrow functions [duplicate]

This question already has answers here:
Methods in ES6 objects: using arrow functions
(6 answers)
Lexical context of 'this' in Nested Object Literals
(2 answers)
Closed 3 years ago.
trying to learn the 'this' key word inside an arrow function properly.
after reading and watching some videos i understood that with the regular function the 'this' key word will be defined whenever the function is invoked.
and 'this' inside the arrow function will be defined according to the value of 'this' wherever you build that function.
so i opened the console and played with two objects and the two functions.
i did this:
const reg = {
reg1: "reg1",
reg2: {
reg3: 'reg3',
regFunc: function(){console.log(this)}
}
}
const arrow = {
arrow1: "arrow1",
arrow2: {
arrow3: 'arrow3',
arrowFunc: () => {console.log(this)}
}
}
reg.reg2.regFunc()
VM712:5 {reg3: "reg3", regFunc: ƒ}
arrow.arrow2.arrowFunc()
VM712:13 Window {parent: Window, opener: null, top: Window, length: 1, frames: Window, …}
for the reg Object i get it because it was invoked inside the reg2 object which it shows me.
but for the arrow Object the this keyword in the arrow function was created inside the arrow2 object inside arrow.
so why isn't the value of it in the arrow object arrow2? why is it the global window?
this is defined for a function execution context.
In the code that defines const arrow there is no function context, only the arrow function. So the lexical this is the global object (in sloppy mode) or undefined in strict mode.
It is a common misunderstanding that an object literal (the one assigned to arrow or to arrow2) would somehow bind this to it.
In arrow functions this is treated similarly to a normal variable (a constant one). An arrow function records the value of this at the moment of creation and this will always point to that value inside the arrow function (since you can't reassign this).
Because arrow functions do not bind their own this but instead inherit from the parent scope which in this case is the global object
The this pointer points window object as it is parent. And this in arrow functions always points to the parent scope, here it is window object.
If you wrap that arrow function with class or function(for instance), then this will point that object.
const func = {
b: {
d: function() {
console.log(this)
}
}
}
const arrow = {
b: {
d: function() {
const e = () => {
console.log(this)
}
return e()
}
}
}
func.b.d() >> {d:f}
arrow.b.d() >> {d:f}

Understanding "this" in functions [duplicate]

This question already has answers here:
In Javascript, why is the "this" operator inconsistent?
(8 answers)
How does the "this" keyword work, and when should it be used?
(22 answers)
Closed 4 years ago.
I have this code:
let bar = () => {
let x = 5;
console.log(this.x)
}
bar();
It does not work. I also have this code:
let bar = () => {
this.x = 5;
console.log(this.x)
}
bar();
It does work. I want to make sure I understand why. As I understand it, simply declaring a variable within a function does not make it a value on the function object. Only when declaring this.___ = ____ does it actually become a value on the object.
...is that right?
There are two types of functions in JavaScript with respect to this: arrow functions and non-arrow functions.
function () {}
For non-arrow functions, you can think of this as just another parameter. Where a typical parameter would be set by passing an argument:
function foo(x) {
return x;
}
foo(1); // returns 1
the this parameter is set by how the function is called:
function foo() {
return this;
}
var obj = { foo: foo };
foo(); // returns undefined, because it’s not one of the following
// special forms
obj.foo(); // returns obj, because the function was called with dot notation
obj['foo'](); // returns obj, because bracket notation and dot notation
// work the same
foo.call(1); // returns 1, because a function’s `call` method
// sets `this` explicitly
new foo(); // returns a new object of type `foo`‽ read up!
Every non-arrow function has this implicit parameter called this. The top scope, outside any function, also has a this. It can be a few different things, depending on your environment; you can safely ignore it.
() => {}
Arrow functions don’t have the implicit this parameter. They use the this from their containing scope, like any other variable. In other words, in complete opposition to non-arrow functions, how they’re called doesn’t matter at all; it’s about where the () => { … } is located.
// `this` outside `foo`…
const foo = () => {
// is the same as `this` inside `foo`. always.
return this;
};
Now, tying it all together, your arrow functions are in the top scope, outside of any other function. That means they have whatever this was in the top scope. If that isn’t undefined, you can set values on it, like you’re doing with this.x = 5; in an arrow function. It’s the same this every time, though, and it’s certainly not referring to “the function object”.
As for the first example: declaring variables, like with let x = 5;, has nothing to do with this at all.

Why is this inside an object window? [duplicate]

This question already has answers here:
How does the "this" keyword work, and when should it be used?
(22 answers)
Closed 5 years ago.
Consider the following code:
var obj = {
x: this
}
obj.x turns out to be window. I thought this would refer to obj.
I don't understand how this works in the above situation. Even with late binding such as in JavaScript, shouldn't x refer to the obj object? I understand all other cases for this where its value is determined by how it is called in the code. Can someone please help me understand this behavior of this?
window is the default value for this if you run your code in a browser. As noted in the comments below, this will be undefined if 'use strict'; is in effect.
the value of this changes on the basis of the object where it resides.
example:
1
var test = {
a: 1,
b: function () {
console.log(this.a)
}
}
In this case the value of this will be the containing object.
var test = {
a: 1,
b: function () {
setTimeout(function () {console.log('surprise', this.a)}, 0)
}
}
This piece of code however doesn't give the same result.
Here without strict mode on, on a browser, property a will be accessed over the window.
The reason being the function in the setTimeout doesn't have the access to the object.
2
var someObject = {
value: 1,
someFunction () {
return function () {
console.log(this.value)
}
}
}
var displayValue = someObject.someFunction()
displayValue()
In this case too, this is undefined, as the value of this changes with respect to the object which contains the function being called.
someFunction is a method on the object someObject therefore, the value of this inside would be equal to someObject but the function returned by someFunction is not called by someObject hence the difference.
This refers to Current Execution Context which in this case (which is initial) is window object.
Check this out
More Specific to this question
One important principal about this is that:
this is not assigned a value until an object invokes the function where this is defined. Let’s call the function where this is defined the “this Function.”
So, lets assume you've defined your object this way:
var person = {
firstName :"John",
lastName :"Doe",
showHometown:function () {
console.log (this);
}
}
Since the this keyword is used inside the showHometown method, and the showHometown method is defined on the person object,​ this will have the value of the person object because the person object will invoke showHometown()​.
As you see difference between x in your defined object & mine, is who invokes them which is formally referred to Current Execution Context.

Function object, context and this [duplicate]

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

Categories

Resources