JavaScript: Problem understanding how 'this' works in ES5 and ES6 [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.
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.

Related

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.

How is 'this' working in this context? [duplicate]

This question already has answers here:
Javascript "this" pointer within nested function
(9 answers)
Closed 5 years ago.
I have a question about how the keyword 'this' works in the following context. Here´s a tutorial with the phaser framework and the code looks like the following(I simply merged it together for you):
var game = new Phaser.Game(400, 490);
game.state.add('main', mainState);
game.state.start('main');
var mainState = {
preload: function() {},
create: function() {
this.bird = game.add.sprite(100, 245, 'bird');
},
update: function() {}
};
In the create function there is a 'this'. I think I understand what this does, but this example proved me wrong. The this keyword - in this context- points to mainState, right(just some information: the create function starts as soon as mainState is called to start the 3rd line)?
I can access the bird outside the mainState object (via mainstate.bird), but why isn't it possible then to define a prototype function like the following outside the game object?
mainState.prototype.myFunction() {}
I´ll get an error calling this and I can't explain.
The mainState is an object literal. 'prototype' is a property of function object in javascript used for prototype inheritance.
Javascript Prototype
One thing that always help me remember what the this will be is to look out for who is calling the function, check this snippet
var sayHi = function() { console.log(this.name) }
var yoda = { name: "Yoda", sayHi: sayHi }
var darthVader = { name: "Anakin Skywalker", sayHi: sayHi }
// the `this` here will be the yoda object
yoda.sayHi()
// the `this` here will be the darthVader object
darthVader.sayHi()
window.name = "Global name"
// here, since nothing was specified, the object is the global object, or the window on browsers, this the same as "window.sayHi()"
sayHi()

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.

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.

"this" in JavaScript

I'm trying to understand the syntax of how to put together a JavaScript function as an object.
Q: Is this the right way to do it?
The reason why I ask is because I'm looking at it in Firebug and I was hoping to be able to drill down and see the value of myVar and myVariable, but instead Firebug only says that "this" is an object Object.
var myObject = {
init: function() {
var myVar = 1;
myObject.myVariable = 2;
console.log('"this" when called as an object: ' + this);
}
}
myObject.init();
Also, what's the funny little syntax to call it directly upon declaration? Something about (), but when I remove the last line and put () at the end of the declaration, I get a syntax error.
This will create a string:
'"this" when called as an object: ' + this
But this is not a string, so its toString() prototype gets called. That's why you only see [object Object].
If you want to have Firebug display the actual object, do a simple console.log(this) or to see the contents directly use console.dir(this).
The "funny little syntax" doesn't really apply here, because you're not really creating a "function object" — that's just an object with a property whose value is a reference to a function object.
However, though it's been done to death on Stackoverflow, you're probably talking about something like this:
var myobject = (function() {
var something = { whatever: "for example" };
return {
init: function() {
this.foo = "hello";
// initialize
},
getSomething: function() { return something.whatever; }
};
})();
Now "myobject" is initialized by a call to an anonymous function, which will be thrown away right after that statement. The closure formed by the function invocation, however, remains alive.
Here is a nice reference for JavaScript object creation

Categories

Resources