Why is this inside an object window? [duplicate] - javascript

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.

Related

Why is `this` keyword necessary in calling methods declared in Class declarations in Javascript? [duplicate]

This question already has answers here:
How does the "this" keyword work, and when should it be used?
(22 answers)
How to access the correct `this` inside a callback
(13 answers)
Closed 3 months ago.
This post was edited and submitted for review 3 months ago and failed to reopen the post:
Original close reason(s) were not resolved
In the MDN Docs,
When a static or prototype method is called without a value for this, such as by assigning the method to a variable and then calling it, the this value will be undefined inside the method.
class Animal {
speak() {
return this;
}
static eat() {
return this;
}
}
const obj = new Animal();
obj.speak(); // the Animal object
const speak = obj.speak;
speak(); // undefined
Animal.eat() // class Animal
const eat = Animal.eat;
eat(); // undefined
I dont understand that when we save a normal/static method reference to a variable, why do we lose the reference of this?
Also speak() is like a normal class method. Is this method said to be a prototype method in the text above?
As a solution, it is written:
If we rewrite the above using traditional function-based syntax in non–strict mode, then this method calls are automatically bound to the initial this value, which by default is the global object. In strict mode, autobinding will not happen; the value of this remains as passed.
And the code provided as a solution:
function Animal() { }
Animal.prototype.speak = function () {
return this;
}
Animal.eat = function () {
return this;
}
const obj = new Animal();
const speak = obj.speak;
speak(); // global object (in non–strict mode)
const eat = Animal.eat;
eat(); // global object (in non-strict mode)
“ then this method calls are automatically bound to the initial this value, which by default is the global object.” - in which line does the this method call take place?
Link : MDN Docs link

JavaScript: Problem understanding how 'this' works in ES5 and ES6 [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.
GIVEN:
var box5 = {
color: 'green',
position: 1,
clickMe: function() {
console.log{this)
}
}
The console.log = {color: "green", position: 1, clickMe: ƒ}
In other words pointing at the object "box5".
But add the following code:
document.querySelector('.green').addEventListener('click', function() {
var str = 'This is box number ' + this.position + ' and it is ' + this.color;
alert(str);
});
And you get the alert: "This is box number undefined and it is undefined"
Question: Why is 'this' apparently pointing at the object when I log it,
not when it try to print object values with "this.property"
There is the "hack" self = this and reference properties with self instead of this.
Probably because this is an HtmlElement, and an HtmlElement does not have a property called position or a property called color.
this is a representation of the object that called the current function. And if an event is fired, the callback function is called by the object the event happened to. In this case, an HtmlElement.
If you'd like to get values from an html element, you can try adding them to the dataset of the element. You can use Vanilla Javascript, and jQuery has their own method implementation
Javascript knows to make a this value present when a function is called while simultaneously dereferencing it off of an object. If a function is called, but not simultaneously dereferenced off an object, its this value will be the global object (window, in the case of browsers).
For example, consider this object:
let obj = {
name: 'amazing obj',
func: function() { console.log(this); }
};
If we now say:
obj.func();
We will see the console output obj itself.
But if we say:
let func = obj.func;
func();
We will see the console output the global object.
The difference between obj.func(), and func(), is that javascript sees that in obj.func's case the function is being dereferenced off of obj, and therefore makes obj the value for this.

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

How does the "this" keyword work with objects in JavaScript? [duplicate]

This question already has answers here:
How does the "this" keyword in Javascript act within an object literal? [duplicate]
(4 answers)
How does the "this" keyword work, and when should it be used?
(22 answers)
Closed 5 years ago.
Since I'm trying to grasp the concept of iterables in JavaScript, I built one with the following code:
let range = {
from: 0,
to: 5
};
range[Symbol.iterator] = function() {
return {
current: this.from,
last: this.to,
next() {
if (this.current <= this.last) {
return { done: false, value: this.current++ };
} else {
return { done: true };
}
}
};
};
for (let num of range) {
console.log(num);
}
The Symbol.iterator method returns an object that contains one method (next) and two properties (current and from). The properties within this object are equal to the properties within the object range.
Since current equals this.from and last equals this.to, I assumed that I could use this.from and this.to directly from within the method next as so:
let range = {
from: 0,
to: 5
};
range[Symbol.iterator] = function() {
return {
next() {
if (this.from <= this.to) {
return { done: false, value: this.from++ };
} else {
return { done: true };
}
}
};
};
for (let num of range) {
console.log(num);
}
However, doing this prevented the iteration from starting. Having observed this, I have two questions:
Why can the properties current and last use the keyword this and have it refer to the object range whereas the method next cannot? current, last, and next() are all part of the same object, which is returned by Symbol.iterator.
Also, given that Symbol.iterator() returns a separate object, shouldn't the this keyword within that object refer to that object itself? In other words, shouldn't the properties current and last not be able to access the properties from range using the keyword this? Isn't range a separate object?
The keyword this is complicated. It is wise to avoid using it when there are better alternatives, which there usually are, because it has many gotchas.
With that out of the way, here's the answer: this refers to the activation object (sometimes referred to as context object) that its containing function was called with.
What is the activation object? It is the object the function was attached to when it was called. The activation object for console.log() is console.
However...
const x = {
log : console.log
};
x.log();
... here x.log() is exactly the same as console.log(), except the activation object is x instead of console.
Seems pretty simple, right? It is, sort of. But there's more things to know.
There is a default context object, used when a function is called without being attached to an object. It is the global object, known as window in the browser and global in Node.js.
If the script is running in strict mode, then there is no default context object and it will be undefined if not explicitly called with a context
Arrow functions use lexical scoping and their this value is not the usual context object at all - it is the context object of its parent function from wherever the arrow function was defined
Now let's take the above and apply it to your code. Most importantly, your next() method would work if it were called with the context being the range object. The problem is, under the hood, the engine is basically doing this...
const returnedObject = range[Symbol.iterator]();
returnedObject.next();
... so next is being called with returnedObject as its context, rather than range. But the function which returned the object is called with range as its context. Thus, this is different in each place.
You can actually fix your problem very easily by using an arrow function instead of a shorthand method.
This will work:
let range = {
from: 0,
to: 5
};
range[Symbol.iterator] = function() {
return {
next : () => {
if (this.from <= this.to) {
return { done: false, value: this.from++ };
} else {
return { done: true };
}
}
};
};
for (let num of range) {
console.log(num);
}
this is known to be a tricky thing. So much so that Kyle Simpson dedicated almost a whole book to the topic (You Don't Know JS: this & Object Prototypes). However, in your example the answer is easy - in the second function, this is within the next() function and so, resolves to this function.
To check the scope of this, I am using Chrome's debugging tool. If you pause at the right line, it tells you what this resolves to.

In JavaScript, the first bind determines who "this" is? (Binding it twice or a second time doesn't matter) [duplicate]

This question already has answers here:
Chaining .bind() calls in JavaScript. Unexpected result?
(6 answers)
Closed 7 years ago.
If bind(obj) can return a function with this bound to obj, then wouldn't
fn.bind(obj1).bind(obj2)
return a function with this bound to obj2?
It looks like only the first bind will bind it, regardless of the second bind, or if we bind it twice or more? Is that part of the specs?
Example: http://jsfiddle.net/hah0L3nj/
var obj1 = { name: "Mike" },
obj2 = { name: "Mary" };
console.log(obj1, obj2);
function printName() {
console.log(this.name);
}
printName.bind(obj1)();
printName.bind(obj2)();
printName.bind(obj1).bind(obj2)();
The last line will print "Mike".
I think the reason is that bind is implemented like this:
Function.prototype.myBind = function (obj) {
var self = this;
return function () {
self.call(obj);
}
};
see http://jsfiddle.net/hah0L3nj/1/
So what is done is a tight bound, and any outer bound (extra wrapping) won't really matter. But I wonder if other implementation of bind can do otherwise, and what the spec says.
As far as I can say function.bind() does not modify the function itself. Instead, it creates a new function, a wrapper, that, when called, ensures the bound function always get the same context. Unless you store the result of bind() in a variable, it has no effect.

Categories

Resources