6 ms·
What does ‘that = this’ in JavaScript mean?
- oblib 10y agoNicely done! Thank you for sharing!
- crgwbr 10y agoDespite writing ES6 with arrow functions, I find that I prefer writing `const self = this` than relying arrow-function lexical scoping. Maybe it will change over time, but for now that way seems to make he intent far clearer and less likely to mess up in a future refactoring.
- z3t4 10y agoTo make it more clear, you can use names. For example: function Car() { const car = this; function foo() { car.engine = "v8"; // vs self.engine } }
- nkkollaw 10y agoNot much clearer, if not less. var self = this; and var that = this; are the standard way and the intent is understood right away.
- amelius 10y agoTitle should be "var that = this". Without "var", you're assigning to a global variable which you don't want in most cases.
- chrisseaton 10y agoI'm not a JavaScript expert so I may be wrong, but I don't think that's right is it? If you are in a function scope (which you would be in the context of this article as we're talking about what the receiver is at different points) then variables assigned without any modifier are defined as locals, in the scope of that function. They are hoisted to the function scope, out of any block scope, unless you use 'var', but they're still locals aren't they?
- JasonSage 10y agoNo, they're actually globals.
- sbuttgereit 10y ago"Assigning a value to an undeclared variable implicitly creates it as a global variable (it becomes a property of the global object) when the assignment is executed." From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
- Animats 10y agoRight. This is a typical language design mistake. It happens in phases: - "We're not going to have declarations in our language. First use defines a variable". - "We need some way to define local variables. But if we make that the default, existing code will break. So the default has to be global." - Embrace the pain. There are variants on this theme. Python is local by default. Go has variable creation by assignment with ":=", but with weird semantics for multiple assignment. Other classic mistakes are "we don't need a Boolean type; 1 and 0 are enough", and "there's only one kind of integer". Fixing those later always sucks.
- 10y ago
- twiss 10y agoNote: Arrow functions cannot help us when the function is defined on the object literal as it will resolve to the enclosing lexical scope, which in this case is the global scope. This is not true. With an arrow function, the example prints "Object Name". MDN says: "An arrow function does not create its own this context, so this has its original meaning from the enclosing context." [1] (The "enclosing context" in this case refers to the context in which the arrow function was created, not the context in which the function in which the arrow function was created was created.) [1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions#No_binding_of_this https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
- sidthesloth 10y agovar name = "Global Name"; var obj = { name : 'Object Name', printName : function() { setTimeout(() => { console.log(this.name); }, 2000); } }; obj.printName(); //prints "Object Name" var printNameReference = obj.printName; printNameReference(); //prints "Global Name" You will see that "Global Name" will still be printed out. The reason is because arrow functions take the enclosing lexical scope, and the arrow function to setTimeout in the example is created each time the printName function is invoked. The printNameReference() invocation sets the scope of the printName function to global because of the way it is invoked and hence the arrow functions to setTimeout will also take this scope. Changing the printName function itself as arrow function does not help either. var obj = { name : 'Object Name', printName : () => { setTimeout(() => { console.log(this.name); }, 2000); } }; The above code will again set the printName function to the enclosing global scope, because that is where obj is declared.
- nawitus 10y agoIf you add "var that = this;" to printName function the printNameReference still doesn't work.
- krptos 10y agoI prefer using `self` rather than `that`, for caching `this`. Must be because I have a strong python background, but generally I find "self" makes more sense than a wild "that"!
- karol 10y agoBy using `self` you shadow a global variable which is a reference to the current context (window object) in which the code is executed.
- imdsm 10y agoI always found context, i.e. let context = this, to be far more descriptive.
- lexicality 10y agoWhich should be accessed by window.self anyway so it doesn't really matter? There are so many poorly named global variables (top etc) that worrying about shadowing them seems meaningless.
- amorgaut 10y agoIt matters when you are running in workers in which case the window object does not exists
- pavlov 10y agoI prefer to use a variable name that describes the type of the object in short. So if my "this" object is actually an AwesomeTableWidget instance, I might do: var table = this; I like the bit of extra documentation it provides... Or maybe this is just a remnant of all the C code I've written over the years, where it's common to have an object pointer as the first argument to a function and it's usually named like this.
- lorenzosnap 10y agoyou are so much better off if you can avoid using this when writing js. It's as bad as (and as useless) the keyword 'new'
- karol 10y agoThis an ugly convention. By always using `that` you lose an opportunity to create a meaningful variable name which would be more descriptive. Why not use? var widget = this Besides using more functional approach and arrow functions you can free up your code from lining methods via this keyword.
- dntrkv 10y agoThat's way more confusing. At least with `that`, you know it is pointing at the current instance. If you see `anyOtherVariableName` you have to know what it was assigned.
- tabeth 10y agoIs it a poor pattern to use #bind a lot instead of this or that? I tend to put most of the code in procedures like functions and bind it to whatever context I need, if not the regular this.
- OSButler 10y agoIf you're using React and you're not using arrow functions, then it's very common to see bind() references.
- seattle_spring 10y agoFor my company, `that = this` means that your code review gets marked as "Revision required".
- kahnpro 10y agoSame here. Bind your functions properly!
- cerved 10y agoI stopped using this altogether and it makes my code better
- boubiyeah 10y agoIt's absolutely useless anyway unless you're trying to slightly optimize cpu and memory usage for at least hundreds of instance creations. Typically this scenario would be found in libs, not in application code. I completely ignore this, prototypes, classes, Function.prototype.bind, etc. Code is much cleaner and easy to follow for devs of all skill level. Also, even if you like these features, var that = this is unneeded if you use a transpiler and have access to the more modern JS constructs like arrow functions.
- sideshowb 10y agoHow do you factor out "this" in cases where methods and instance data logically belong together?
- beaconstudios 10y agoIf you're completely getting rid of "this" references then you're probably following a functional style and will keep data and functions separate, passing pure data as arguments rather than combining data and functions into classes.
- boubiyeah 10y ago1) Either use a functional style like beaconstudios said where it's perfectly normal to separate the data and the processing. 2) Or if you want to keep an OO style, use the module pattern with private functions closing over the data.
- cerved 10y agoUsing an object factory and referencing the object within the factory's lexical scope
- deleted 10y ago[deleted]
- DonHopkins 10y agoIt means JavaScript was a poorly designed language.
- ams6110 10y agoNot sure I'd go that far but it definitely has its warts, like all languages, and developers need to understand what they are.
- DonHopkins 10y agoDon't get me wrong: I love JavaScript, I write piles of it all the time, and I said "was" not "is" because it's been vastly improved since it was originally badly designed, but I still get screwed by accidentally using "this" in the wrong context. It's such an easy accident to make, and it's so hard to see, because when you're looking at code you wrote, you see what you meant to write, instead of what's actually there. Programming languages are user interfaces, and "this" is a user interface dark pattern, an unforced design mistake that doesn't make the language any more powerful, but lays a deadly trap for beginners that also bites pros. It's tricky to understand and hard to explain (this is actually a dynamically bound keyword, not a lexically bound variable), so it's fodder for the thousands of blog posting explaining it like the one we're discussing.
- deleted 10y ago[deleted]
- golergka 10y agoIs there a single instance in real JS code where it's this binding is actually useful?
- jasonkostempski 10y agoIt depends on what the meaning of the word "it's" is.
- gbuk2013 10y agoYes - if you want to use this inside a callback within your function.
- golergka 10y agoOh, I wasnt being clear. I meant the default binding behaviour, not using .bind().
- gbuk2013 10y agoOne common example would be to refer to instance properties of an object from a method that is attached to the object's prototype. Actually I think using bind() would be a very unusual thing, but that could just be my style of writing code (I don't think I've ever used it in any code I have written over the years).
- adolph 10y agoSince nobody has mentioned it yet, my first introduction to that = this; was JavaScript: The Good Parts, Unearthing the Excellence in JavaScript by Douglas Crockford Well worth a read for understanding the differences and relative powers of a prototypical language and how to get it to behave almost like a classical one. I think the one big thing it missed was immediately envoked function expressions. http://shop.oreilly.com/product/mobile/9780596517748.do http://shop.oreilly.com/product/mobile/9780596517748.do
- Animats 10y agoIf you have closures, you can simulate objects. In many different ways, most of them bad. If you have an interpreter with decent variable semantics, you get closures. That's how LISP did objects in the 1980s, before people knew better. Javascript somehow got it from there. Why do we have to keep reviving the bad ideas?
- kazinator 10y agoLisp had CLOS in the 1980's, and before that, precursors to CLOS.
- lispm 10y ago> you get closures. That's how LISP did objects in the 1980s, before people knew better That one can use closures for objects was demonstrated with Scheme in the 70s. See for example: Scheme: An Interpreter for Extended Lambda Calculus". MIT AI Lab. AI Lab Memo AIM-349. December 1975. http://library.readscheme.org/page1.html http://library.readscheme.org/page1.html It's also a typical topic in education to show how to use closures to implement a primitive object system, similar how one learns to 'implement' numbers in pure lambda calculus. But actual object systems in Lisp from the 70s/80s mostly did not use closures as objects. None of LOOPS, Flavors, CLOS, KRL, KEE, FRL, ... uses closures for their implementation. Even in 'Object Lisp', which is relatively close to Javascript's objects, they don't use closures: http://www.unlambda.com/lispm/lmi-source/extract/dj_full/l/objectlisp/ http://www.unlambda.com/lispm/lmi-source/extract/dj_full/l/o... In http://www.unlambda.com/lispm/lmi-source/extract/dj_full/l/objectlisp/obj.lisp.155 http://www.unlambda.com/lispm/lmi-source/extract/dj_full/l/o... you can see that objects in Object Lisp were implemented by using structures (aka records), not closures.
- deleted 10y ago[deleted]
- nunez 10y agothis should never be that complicated.
- jaypaulynice 10y agoI use var _this = this
- Vanit 10y agoI try to omit this convention by promises or bind() when possible, but sometimes when using 3rd party libraries it's a necessary evil.
- sidthesloth 10y agoThis a follow up post on how to replace 'that = this' assignments with arrow functions: https://dbwriteups.wordpress.com/2017/04/14/replacing-that-this-assignments-in-javascript-with-arrow-functions/ https://dbwriteups.wordpress.com/2017/04/14/replacing-that-t...