
‘This’ in JavaScript - zellwk
https://zellwk.com/blog/this/
======
rjeli
I don't like the explanation as a set of piecewise cases. _this_ just refers
to the current object context. _this_ refers to the window at the top level
because you're operating within `window`. There aren't "simple functions" and
"object constructor functions", just functions, and the `new` keyword executes
the function within the context of a new object. Event listeners are not a
special case, it's just that the callback is executed from the context of the
event -- which makes the difference between `function (e) { this }` and `e =>
this` much easier to understand.

~~~
carussell
The unfortunate thing about the lengths people go to in order to try to "fix"
`this` in event handlers is that it wouldn't be a problem if people just
implemented the event listener interface correctly.

PSA Don't do this:

    
    
      proto.foo = function() {
        /* ... */
        var self = this;
        element.addEventListener("click", (function(event) {
          self.iHaveAnUnhealthyObsessionWithLambdas(event.target);
        }));
      }
    
      proto.iHaveAnUnhealthyObsessionWithLamdas = function(clicked) {
        /* do something with clicked element `clicked` */
      }
    

Do this instead:

    
    
      proto.foo = function() {
        /* ... */
        element.addEventListener("click", this);
      }
    
      proto.handleEvent = function(event) {
        /* do something with clicked element `event.target` */
      }

~~~
amelius
The problem is that the approach is different depending on context. You are
making use of the assumption that the addEventListener function knows to call
the "handleEvent" method of the object in the second argument, and give it a
proper "this" object. That's a big assumption, which should be documented in
the code.

The code using "self" doesn't have this problem; it's more self-contained so
to speak (no pun intended).

~~~
kitd
Agreed. Much prefer 'var self = this' style. Keep the model transparent for
future maintenance.

One time I don't is in Jasmine, where they explicitly state that 'this' is
shared across all 'beforeEach', 'it' and 'afterEach' calls. Which backs up
your first point.

~~~
nkozyra
I thought self had gone out of favor due to its relatively new global purpose.

~~~
kitd
ok, call it something else. I meant to say, save away the current ref to
'this'.

------
Yaggo
It's possible to write javascript without `this`, a style preferred e.g. by
Douglas Crockford, explained in the video below.

[https://www.youtube.com/watch?v=PSGEjv3Tqo0](https://www.youtube.com/watch?v=PSGEjv3Tqo0)

I've also started to write my code mostly without `this`, `class` or `new`,
not looking back.

Another related, highly recommend reading: [https://medium.com/javascript-
scene/the-two-pillars-of-javas...](https://medium.com/javascript-scene/the-
two-pillars-of-javascript-ee6f3281e7f3)

~~~
boubiyeah
Me too (and later my organization)

It doesn't bring anything (except a bit more performances when you create tons
of objects, a setup that rarely matters unless we're talking video games or
some very niche applications that somehow can't work with a subset of your
data) but only create more cognitive load (bind, call, =>, closures using
this, where Am I? is it a method or a function? Is it already pre-bound?).

Functionalities that create extra cognitive load and doesn't give you anything
shouldn't be used.

~~~
jholman
I absolutely agree.

As a related side rant, the `new` keyword, or equivalent, makes great sense in
a manual-memory-management language like C, and it's an offense to sanity in a
language like Java or Javascript. Factory functions should be the default
everywhere. So any JS coding style that encourages `new` is a wildly bad fit
to the rest of the language.

But it _is_ important to admit the caveat, as you do, which is "when you
create tons of objects".

Such situations are unequivocally in the minority (compared to line-of-
business stuff where RAM and CPU more than sufficient to the task), but not
the _vanishing_ minority. So we do still need a good solution for those.

Rendering, simulation, sampling/signal-processing, parsing... the list goes
on. This isn't truly systems-level code, but it's easy to generate a billion
objects per second. So we do need patterns for doing this kind of programming.

~~~
int_19h
> Factory functions should be the default everywhere.

Factory functions still need to create the object somehow to return it.

~~~
jholman
Absolutely. The guts of the factory function should usually involve an object
literal. Or in some cases, Object.create.

(If we're talking about Java, then obviously you have to have `new` somewhere,
which is just one of the many shortcomings of Java, although obviously not a
fatal one.)

~~~
sethrin
I do really like JavaScript's ability to compose objects like that, and I feel
that people interested in it as a language should definitely learn how to
program in that manner. However, I suspect that for most people JavaScript is
a means to an end, and it's more useful in a number of senses to try to write
JavaScript more like other class-based languages. I mean, I feel like things
like TypeScript sort of miss the point of having a dynamically typed language,
but there is a solid case to be made for features like strong typing,
especially as size and contributors go up.

------
mattmanser
Crazy we're still talking about it.

I thoroughly understand `this` now after over a decade working in javascript,
as well as thoroughly understanding `this` in Typescript which I use more now.

And I still make a mistake at least once a week. I know what I've done as soon
as the code fails, but it's still so ridiculously easy to get into a context
you didn't think you were.

Of all the mistakes made in javascript, `this` stands head and shoulders above
everything else, with its arm round the prototypal class structure.

~~~
christophilus
I almost never use "this" in my JS code. I find that when you use a functional
style of development, you largely avoid the "this" pitfall.

~~~
mattmanser
That debate is long over.

If there's anything that a decade of functional style being "the next big
thing" has taught us, functional style is not "the next big thing" and most
programmers don't work well in it.

~~~
disantlor
i strongly disagree with this. half of my posting history on here is
evangelizing FRP in javascript (in my case via bacon.js).

it has dramatically reduced the amount of time i spend on these and many other
sorts of problems. honestly it makes programming way more fun. maybe haskell
is a bit extreme for most situations but the concepts are not.

~~~
mattmanser
While you may love functional, and I'm not saying you shouldn't, I think
you're strongly disagreeing with the statement you think I'm saying,
"functional is bad", rather than the actual statement I'm making which is
"functional programming's had many chances to become a mainstream language and
it never takes off (outside a few specialities)".

What evidence do you have that functional is taking off? Since this board was
around, every couple of years there's been a flurry of 3 months when a chunk
of the community bangs on about functional programming.

First it was Lisp, then Erlang, then Haskell, then F#, then Scheme. I might
have got the order wrong.

And it never, ever, ever takes off because while 10% of programmers find
functional truly brilliant, the other 90% can't work with it.

For context, in that time Ruby (via Rails), Python (via Django and use in
Science), javascript server-side (Node.js), Go, Swift, Rust and now possibly
Kotlin have all taken off. Plus various other techs like NoSQL.

~~~
christophilus
Hm. I guess it depends on your definition of mainstream.

In the front end space, functional programming is taking off, I think. Could
be wrong, but React + Redux + immutablejs is a popular and very functional
approach to UI.

Elixir appears to be on the same trajectory as Rails in it's early days.
Anectodally, I know a lot of Rails devs and shops that are now primarily
Elixir.

Most mainstream languages have adopted functional styles and best practices.
Higher order functions, a general acknowledgement of the benefits of
immutability, etc.

Fp may not be mainstream, whatever that means, but it's more popular than I
can ever remember it being.

------
morecoffee
The numerous overloads of 'this' is one of the things that turned me off from
JS. It's great that bloggers explain the usages and how it works in different
scenarios, but really the better solution would be to not have the problem at
all. I would trade overloading for verbosity. An editor can easily squash the
latter, where as a human has to train for the former.

~~~
Sacho
But there is no "overload" to `this` in JavaScript. It works the same way
every time. It's an implicit parameter that is passed when you call the
function. It can also be bound, just like all the explicit parameters. The six
ways the author presents are just an incomplete list of "Ways you can create
an execution context in JavaScript".

This may be confusing to people who expect `this` to have a certain
functionality when coming from a different language, but `this` is very
consistent in JavaScript. It's just not the kind of consistency people seem to
expect.

There's a great way to avoid having the problem - don't use the implicit
parameter! What exactly is it giving you, anyway? In almost all cases where
people fail to use `this`, they essentially create a function to pass it
explicitly. Why not just do that from the get go?

~~~
yarrel
It may work the same way every time, but the way it works the same is
different depending on context.

------
eiriklv
Simple(r) explanation; this is whatever is "left" of the function call (i.e -
obj.method() => this === obj inside the called method), unless you've used
.bind/call/apply which explicitly sets what this should be via an argument.

If you're doing a direct function call like myFunc() there is nothing "left"
of the function call. But you might think of it as actually doing
window.myFunc(), which again explains why this === window. In strict mode this
behavior has been "fixed" so that this === undefined.

It's all about how a function is called.

~~~
Cakez0r
What about setTimeout(obj.method, 1)?

(Spoilers: this == window, not what is left of the function call)

~~~
eiriklv
As nhpatt notes you're not actually calling obj.method here, you're passing it
as an argument, which will be called at a later time.

Looking at a possible implementation of setTimeout makes it clearer:

    
    
      function setTimeout(func, delay) {
        // wait for the delay to complete..
        func();
      }
    

Here you can see that when the function is called there's nothing to the left
of it.

~~~
Cakez0r
Yup, I get it. I was just pointing out that there are some edge cases to the
"context is whatever is left of the function" rule-of-thumb.

------
z3t4
Always name "this" and it will be easier to understand the context

    
    
      function Car() {
        var car = this;
      }
    
    

And if it already have a name, use that name:

    
    
      var foo = {
        bar: 1,
        say: function say() {
          console.log(foo.bar); // foo instead of "this"
        }
      };

------
sAbakumoff
"You don't know JS" series dedicated the whole book to "this" mystery :
[https://github.com/getify/You-Dont-Know-
JS/blob/master/this%...](https://github.com/getify/You-Dont-Know-
JS/blob/master/this%20&%20object%20prototypes/README.md#you-dont-know-js-this
--object-prototypes) Read this, 3 times maybe, and you will become the master
of this.

------
balabaster
Sometimes I wanna throw my hands up in the air and scream this is bullshit.
But I can never figure out what this is

------
_frog
Somewhat off-topic, but I saw your newsletter sign up form partway through the
article and thought to myself "I would like to see new articles from this
blog". The issue is I don't want to sign up for yet another email newsletter,
and would much rather subscribe to an RSS / Atom feed. Do you have any plans
to add one?

~~~
icebraining
If you can't get a positive reply, I suggest
[http://emails2rss.appspot.com/](http://emails2rss.appspot.com/)

------
chrismorgan
There is an error in this article:

    
    
      const sayThis = _ => console.log(this)
      const boundFunc = sayThis.bind({hippy: 'hipster'})
      boundFunc()
    

Because you used an arrow function, `this` is _not_ {hippy: 'hipster'}. You
can’t rebind functions; once they’re bound, they’re bound.

------
scandox
> bind is a method that is present in every function

There is surely a world of unexplained knowledge in that line for someone that
doesn't know JS well

------
FeepingCreature
In Jerboa, my JS-inspired scripting language, there's an alternative to the
"function" keyword called "method". The only difference is that "method"
functions expose `this' and "function" functions don't.

This removes the need for the `var self = this' hack and all the related
weirdness.

An amusing consequence is that if you declare a simple closure as a method,
its `this' pointer will be the stackframe of the lexical context where it is
called.

    
    
        method test() { print(this.a); }
        var a = 5;
        test(); /* implicitly __stackframe__.test() */
    

(You should not actually do this, of course. It's fun though.)

The reason is straightforward: the `this' pointer is the object on whose
lookup the closure was found...

------
kough
So many new guides to `this` in the comments here. Not sure why this blog post
exists either. I agree with most people that JS is confusing to people who are
used to OOP programming in Python or Ruby, and that "this" is one of the most
confusing parts. The best resource I've found is
[https://bonsaiden.github.io/JavaScript-
Garden/#function.this](https://bonsaiden.github.io/JavaScript-
Garden/#function.this) . Free, online, concise, accurate.

------
vkjv
Here's a fun one about `this` that you might not know. When running `eval`,
`this` refers to the `this` in the calling context. Unless you alias the
method. Then it refers to the global context.

    
    
        class Test {
            eval() {
                return eval('this');
            }
    
            aliasEval() {
                const e = eval;
    
                return e('this');
            }
        }
    
        const test = new Test();
    
        assert.equal(test.eval(), test);
        assert.equal(test.aliasEval(), global);

------
dvt
_this_ is certainly tricky in JS :) I remember answering a question in a
similar vein on SO a few years ago:
[https://stackoverflow.com/questions/6039265/50-50-false-50-5...](https://stackoverflow.com/questions/6039265/50-50-false-50-50-true/6039428#6039428)

(I can't believe it was 6 years ago, time flies.)

------
Waterluvian
`this` was the single-most challenging thing when I was learning JavaScript
organically by myself. Now that I get it, it's pretty simple, but I also love
that with arrow functions, I've had to worry about the unboundedness of `this`
far less.

------
k__
Somehow, after I understood this and prototypes in JavaScript it felt more OO
than Java to me.

------
ahmedfromtunis
Coming from an 00P background, I never grasped this, and why it was made in
such a way.

This made me avoid JavaScript as much as possible. Fortunately, I finally
dived in, building my first js heavy webapp -- without a single this in it.

------
sbr464
Not an incorrect article, but my opinion is that the focus should be informing
people to not use this at all and more education on immutable data vs
confusions on this

~~~
ryan-allen
I agree, I only use this in classes in JS, outside of that usage I see it as
an anti-pattern.

~~~
mikekchar
The one place I've used "this" outside the context of a class is when I built
a monad as an object and decided to use set the "this" context to be the
monad. So, for example "return/unit/pure" (or whatever you want to call it :-)
) is available as "this.return". In that way the functions passed to "bind"
can be generic and still build the correct monad.

There are other ways to do it, but this struck me as the first time I had
fiddled with "this" and felt that it was a reasonable idea.

------
halis
`this` in Javascript is an anti-pattern and so is this article...

I wish classes didn't make into ES6, object-oriented programming is a waste of
time.

------
vesinisa
What is the syntax used in the third example of "This in an object method"? I
have never seen it, looks like an error to me.

~~~
jholman
When you say "looks like an error", did you try running it? I assume you have
a web browser handy.

All the examples in that section both look correct to me, and run as I'd
expect in the JS environment I have closest-to-hand.

If you want help on the syntax, you should pose a more-specific question.
Exactly what code looks like an error, and why do you think it's an error, and
so on?

~~~
vesinisa
Sorry, I was on mobile and could not run it in the browser console. It was an
honest question, but I already got the answer.

------
stevefan1999
that is why sometimes we need to bind the this context in say like in jquery
or react event handlers, they have different this every time! what a confusion
isn't it?

------
partycoder
And in non-strict mode this behaves differently as well.

------
taw55

        this = "madness!";
        if (this === "madness!") {
            this = "SPARTA!!!";
        }
    

(sorry)

------
byteface
thanks for sharing

------
bluepnume
I'm not sure I like this guide, because in several places it seems to imply
the value of `this` is decided by where you define the function, which is only
really true for arrow functions. For regular functions, unless you take
control of `this`, it will be decided by the caller.

Best way I can think to describe `this`:

\-----

1\. Either you decide in advance exactly what you want `this` to be:

\- Use `.bind()` on your function and fix the value of `this`

\- Create an arrow function and get `this` from the lexical scope

\- Alias `let self = this` in your desired scope, and only ever reference
`self`

\- Create a wrapper function which fixes the value of `this` (essentially,
implement `.bind()`)

\-----

2\. Or `this` will be decided by your caller:

\- Your caller will `.bind()` your function with an unknown value of `this`

\- Your caller will call `.call()` or `.apply()` with an unknown value of
`this`

\- Your caller will attach your function to an unknown object, then call
`unknownObject.yourFunction()`, setting `this` to `unknownObject`

\- Your caller will call your function as a standalone function: `let newFunc
= someObj.someFunc` - then call it, setting `this` to `global` or `window`

\- Your caller will pass your function as a param to something like
`setTimeout` and achieve the same effect, setting `this` to `global` or
`window`

\-----

Obviously, most of the time if you're going to use `this`, #1 is to be
preferred, #2 is to be avoided, so it's imperative to decide in advance what
you want `this` to be rather than allowing it to be decided by your caller.

(Unless that's absolutely what you want, and you have a good reason why --
like if you're writing a wrapper function which is agnostic to the value of
`this` that's passed)

~~~
bshimmin
I always advise against calling your `this` alias `self`, because of
[https://developer.mozilla.org/en/docs/Web/API/Window/self](https://developer.mozilla.org/en/docs/Web/API/Window/self)
\- ie. if you missed out the `let self = this` line, then `self` will still
work but it'll refer to `window`.

~~~
fenomas
Surely this is going a little too far - there are _tons_ of similarly
innocuous names that will refer to globals if you forget to declare them.
_name_ , _top_ , _find_ , _scroll_ , etc.

The real solution to the problem you're describing is strict mode and an
editor that highlights undeclared variables!

