I read "Why and how to bind methods in your React component classes?" and grabbed the basic idea of how different is this
by the scopes it gets called.
I made a simple class to test this.
class Something {
constructor(some) {
this.some = some;
}
print() {
console.log(
"print from ",
this,
this === undefined ? "!!this is undefined!!" : this.some
);
}
}
From what I understood, the scope of this
can be different although it is from the same object (instance).
const some = new Something("is");
some.print(); // 'this' is defined. 'this.some' is 'is'.
const going = some.print;
going(); // 'this' is undefined.
going.call(some); // 'this' is defined. 'this.some' is 'is'.
But then, why is this
(which should be the object itself) undefined
in the latter case? Shouldn't it be the top-level this
, which is an empty object {}
?
Here, in the first line, you're storing a reference to the
print
function (property) of thesome
object in the variablegoing
.Note, you're just storing the reference to that particular property (
print
), not along with the owner (some
).this
refers to the 'owner' always.So when you execute
going
, the owner (this
) is unknown (or call itundefined
).there's a function
print
when you call it like this
that effectively gets translated to this
When you just pull it out
You've just gotten a reference to the standalone function so calling it with
Is the same as calling
It's the
.
betweensome
andprint
that is magically passingsome
asthis
toprint
.going()
has no period so no this is passed.Note that you could assign going to an object and use the period operator to do the magic "pass the thing on the left as
this
" operationall the
class
keyword does is help assign print toSomething
's prototypeis the same as
which is also effectively the same as this
Saikat showed using
bind
. Bind effectively makes a new function that wraps your old function. ExampleIs nearly the same as
Some of the other answers have appear to have a fundamental mis-understanding of
this
.this
is not the "owner" nor isthis
the current object.this
is just effectively another variable inside a function. It gets set automatically if you use the.
operator with a function call. soa
.
b()
setsthis
toa
. if the dot operator did not exist you could still setthis
by usingcall
orapply
as insomefuntion.call(valueForThis, ...args)
orsomefunction.apply(valueForThis, [...args])
;Also note that ES6 added the
=>
arrow operator which bindsthis
to whatever it was when the function is created. In other wordsIs the same as
it should also be clear that both functions made with
bind
and arrow functions you can not changethis
usingcall
orapply
since effectively they made a wrapper that always setsthis
to what it was when the wrapper was made just likecreateAFuncitonThatPassesAFixedThis
did above.Let's add some comments to show what I mean
One more thing. It's very common to use
bind
to make a function for an event listener or callback. It's very common in React. ExampleThis would be handled in at least 3 common ways.
Using
bind
in the constructor (see above)Using
bind
in renderUsing arrow functions in render
Above I showed what
bind
and=>
actually do withcreateAFuncitonThatPassesAFixedThis
. They create a new function. So that should make it clear that if use style 2 or 3 above when every single timerender
is called a new function is created. If you use style 1 then a new function is only created in the constructor. It's a style issue as to whether or not that's important. Creating more functions means more garbage which means a possibly slower webpage but in most cases unless you have a crazy complicated webpage that is rendering constantly it probably doesn't matter which of the 3 ways you do it.you should correct this line to
Otherwise going is getting a different scope and its not an member of some object so
this
isundefined
NOTE
this
refers to the current class object. Andgoing
is not a member of any class sothis
isundefined