DEV Community

Cover image for 🧐Most Confusing Part Of JavaScript.

🧐Most Confusing Part Of JavaScript.

Chetan Atrawalkar on July 20, 2021

If you are working with javascript for a while, you will agree with me. This ‘this’ keyword is very confusing when you are writing code, especially...
Collapse
 
pepkin88 profile image
Marek Pepke

I see this as an implicit zeroth parameter of a function.
You can explicitly assign its value by using the .call or .apply or .bind methods.
Event listeners provide the event object as the first argument and the receiving element as the zeroth argument this.

But I get that it is confusing, by its implicitness and by having many rules associated with it.

However, I don't know why have you suggested React Hooks as a remedy for this. You know that React isn't everything, right? People use JS for other things than React.

Collapse
 
vineyrawat profile image
Viney Rawat

It's literally very easy concept 😉

Collapse
 
peerreynders profile image
peerreynders

Quote:

The venerable master Qc Na was walking with his student, Anton. Hoping to prompt the master into a discussion, Anton said "Master, I have heard that objects are a very good thing - is this true?" Qc Na looked pityingly at his student and replied, "Foolish pupil - objects are merely a poor man's closures."

On his next walk with Qc Na, Anton attempted to impress his master by saying "Master, I have diligently studied the matter, and now understand that objects are truly a poor man's closures." Qc Na responded by hitting Anton with his stick, saying "When will you learn? Closures are a poor man's object." At that moment, Anton became enlightened.

By moving from classes to hooks React simply moved from one stateful system to another - from objects to closures.

Deep dive: How do React hooks really work?

Interestingly the Elm community has pretty much come to the conclusion that "components" don't work in a functional system - i.e. Model, Update, and View are three separate systems. While each can be broken down into smaller units, it's a mistake to throw a little piece of model, update and view into an aggregating whole.

So React's claim to being functional is only skin deep - at its core it's still object-oriented even if it prefers to use closures.

Collapse
 
ash_bergs profile image
Ash

While I don't know if I'd say it's the most confusing part, this can certainly take on a lot of complexity once we start taking arrow functions and other peculiar little things into account.

That said, even new developers should have a grasp of this, and the things that can impact it. I don't see hooks as a "solution" because this isn't a problem. Using it can give you all the power, knowing nothing about it could take all that power away.

Thanks for writing and starting a conversation!

Collapse
 
chetan_atrawalkar profile image
Chetan Atrawalkar

Thanks for share your thoughts

Collapse
 
peerreynders profile image
peerreynders • Edited

➡️ this has a different values depending on where it is used.

No. For a regular function it depends on how it's invoked - not where it is used. For arrow and bound functions 'this' is fixed permanently.

➡️ Inside a method this refers to the owner object.

Only when called through the object reference either with dot notation obj.fn or index notation obj['fn']. A function isn't owned - it can merely be used in the manner of a method. Unless you are using arrow or bound functions explicitly, objects constructed via class still use regular functions as methods to facilitate implementation inheritance. For regular functions 'this' is bound dynamically at runtime when the function is invoked. So the same function instance can see different values of 'this' during its lifetime just like any of its other arguments can vary from one invocation to the next.

➡️ In a event this refers to the element that received the event.

This is only true in React when a regular function is bound in the constructor or render or with an arrow function (automatically bound to the object inside the constructor or the render function). Function expressions (regular or arrow) created inside functional components use the references returned by hooks (instead of 'this') to reference data inside the closures that React is managing on the component's behalf.

React's synthetic event system didn't bother implementing event-handling-by-object as it is implemented in the DOM via the EventListener.handleEvent() method. In his usual enterprising manner Andrea Giammarchi (WebReflection) found a way around that.

With regular DOM events Event.target is the element on which the event occurred while Event.currentTarget identifies the current target element for the event as the it traverses the DOM during the event bubbling or capturing phase.

Collapse
 
chetan_atrawalkar profile image
Chetan Atrawalkar

Hello Everyone,
This topic is so controversial and I'm already mentioned this point in my post. And with this keyword every developers has different opinions with there knowledge or some experience but my request to everyone just comment your opinion regarding this. So, don't argue with each other and don't say that anyone will feel inferior as he is sharing his experiences. So don't argue with anyone because in the end we're all developers.

Stay Happy ❤️🤗 Stay Focused ❤️
😎Keep Claim And Just Code It!

Collapse
 
ats1999 profile image
Rahul kumar • Edited

If you know oops then this is no more confusing for you, but the way we use this in JS is confusing.

Collapse
 
peerreynders profile image
peerreynders • Edited

Approaching JavaScript with a classical object oriented mindset sets you up for failure and familiarity with class-based OO programming sets you up for confusion with 'this' in JavaScript.

Forget about what 'this' means in OOP languages and approach 'this' as an entirely new and independent concept. Remember JavaScript didn't get classes until ES2015 and even then those "classes" aren't "classical":

Quote

Classes are a template for creating objects.

Objects aren't members of the creating class for life (they can be augmented at runtime) and neither do objects even need a class to be created. So while class is more than syntax sugar it's not about classical OOP.

Pre- class (ES5.1 and earlier)
11.1 The 'this' Keyword

The 'this' keyword evaluates to the value of the ThisBinding of the current execution context.

That's it. Nothing about objects and class didn't even exist yet. If you felt compelled to practice classical OO with JS you had to learn about prototype chaining, constructor stealing and combination, prototypal, parasitic and parasitic combination inheritance.

Under 10.3 Execution Contexts

An execution context contains whatever state is necessary to track the execution progress of its associated code.

In practical terms this means that in general inside a function fn() the ThisBinding is determined by the way the function is called:

  • Call the function directly fn() then 'this' is the same as it would be for code at the top-level: undefined in a strict environment or globalThis in a non-strict environment.
  • When a function is invoked via the new operator 'this' refers to the object under construction.
  • Call the function via an object reference e.g. record['fn']() or record.fn() then the object will be bound to 'this'.
    • This mimics a method call but also enables reuse of a function bound to the prototype object for an object with that prototype object.
    • So just copying the function reference from an object property doesn't carry the ThisBinding with it.
  • Both Function.prototype.apply() and Function.prototype.call() give direct dynamic control over the ThisBinding.
  • Function.prototype.bind() creates an entirely new function which has its ThisBinding permanently bound to the specified context.

  • ES2015 introduced arrow function expressions not as a shorthand for function () but as a bind -ing convenience as arrow functions will always bind their 'this' to the 'this' of the context that creates them.

Aside: JavaScript is Function-Oriented

<!DOCTYPE html>
<html>
  <head>
    <title>JavaScript ThisBinding</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
  </head>
  <body>
    <p>Check the console</p>
    <script>
     // non-strict mode
     const record = {
       data: 42,
       fn: showFunctionContext,
     };
     const justData = {
       data: 2021,
     };

     console.log('script global', globalThis); // Window
     console.log('script top-level', this);    // Window
     showFunctionContext();                    // Window
     record['fn']();                           // {data: 42, fn: ƒ}, data 42
     record.fn();                              // {data: 42, fn: ƒ}, data 42
     showFunctionContext.call(justData);       // {data: 2021}, data 2021
     showFunctionContext.apply(justData);      // {data: 2021}, data 2021
     const newFn = showFunctionContext.bind(justData);
     newFn();                                  // {data: 2021}, data 2021
     const arrowOne = makeArrowFunction.apply(undefined);
     arrowOne();                               // Window (i.e. undefined was replaced with globalThis)
     const arrowTwo = makeArrowFunction.apply(justData);
     arrowTwo();                               // {data: 2021}, data 2021

     function showFunctionContext() {
       console.log('function in script', this);
       if (this?.hasOwnProperty('data')) {
         console.log('data', this.data);
       }
     }

     function makeArrowFunction() {
       return () => {
         console.log('arrow function', this);
         if (this?.hasOwnProperty('data')) {
           console.log('data', this.data);
         }
       };
     }
    </script>

    <script type="module">
     const record = {
       data: 42,
       fn: showFunctionContext,
     };
     const justData = {
       data: 2021,
     };

     console.log('module global', globalThis); // Window
     console.log('module top-level', this);    // undefined
     showFunctionContext();                    // undefined
     record['fn']();                           // {data: 42, fn: ƒ}, data 42
     record.fn();                              // {data: 42, fn: ƒ}, data 42
     showFunctionContext.call(justData);       // {data: 2021}, data 2021
     showFunctionContext.apply(justData);      // {data: 2021}, data 2021
     const newFn = showFunctionContext.bind(justData);
     newFn();                                  // {data: 2021}, data 2021
     const arrowOne = makeArrowFunction.apply(undefined);
     arrowOne();                               // undefined
     const arrowTwo = makeArrowFunction.apply(justData);
     arrowTwo();                               // {data: 2021}, data 2021

     function showFunctionContext() {
       console.log('function in module', this);
       if (this?.hasOwnProperty('data')) {
         console.log('data', this.data);
       }
     }

     function makeArrowFunction() {
       return () => {
         console.log('arrow function', this);
         if (this?.hasOwnProperty('data')) {
           console.log('data', this.data);
         }
       };
     }
    </script>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode
Collapse
 
saoud profile image
Saoud

I’m learning react now and I’m excited about it since it seems like it’s really powerful.

Collapse
 
deepbb profile image
Pradeep

Thank you and Nicely explained, even I have been using React hooks and hadn't used 'this' yet, but while writing in plain JavaScript using Classes i have a bit confused about 'this'.

Collapse
 
larsejaas profile image
Lars Ejaas

My problem with the 'this' keyword is that you basically go against what is normally considered best coding practices.
'This' can refer to different elements or objects in the code, where with functions, objects etc. you always strive to use descriptive unique naming. I know 'this' is an integrated part of modern Javascript, but I can't shake the feeling that it introduces some level of confusion and decrease readability of the code. This is not bad practice, but to me it will never really feel like the cleanest solution either.

 
peerreynders profile image
peerreynders

People just keep going on how "functional" React is - that is just veneer for developer experience. From a systems perspective it isn't functional at all - Elm is functional.

I didn't mention OOP or classes as such. When it comes right down to it there is just very little difference between using mutable state in the shape of object instances or closures.

 
chetan_atrawalkar profile image
Chetan Atrawalkar

Wrap the particular word with ``.

Collapse
 
blackr1234 profile image
blackr1234

Agree, I think I have never needed to use this with React Hooks.

Collapse
 
chetan_atrawalkar profile image
Chetan Atrawalkar

Thank you u agree so don't forget to like, unicorn 🦄, and save ❤️🙏

Collapse
 
hssanbzlm profile image
Hssan Bouzlima

This article may help, it explains how to determine "this" value.
dev.to/hssanbzlm/javascript-basic-...

Collapse
 
chetan_atrawalkar profile image
Chetan Atrawalkar

Thank for sharing

Collapse
 
chetan_atrawalkar profile image
Chetan Atrawalkar

You mean this highlights

 
chetan_atrawalkar profile image
Chetan Atrawalkar

Yes 🤣 this topic is so controversial, but this post is useful or not please tell your opinion bro.

Thread Thread
 
peerreynders profile image
peerreynders

@lukeshiru I'm not disagreeing with you.


I'm just commenting on the general notion among some React users who claim that React is a technology that is based on the functional paradigm because it makes the "view" a "function" of "state".

It's actually React's component model that makes it popular and it's component instances that make React an object-centric technology.

A function component may just be a function - but that function manages any number of stateful component instances while also rendering their part of the view.

The function's props are dynamic data from the owner component instance of the current component instance being rendered and hooks give the function access to the current component instance's mutable state.

So even when exclusively using function components (with hooks) in React the approach is still object-centric due to the foundation of mutable, stateful component instances (absence of 'this' notwithstanding).


Even back in 2008 Douglas Crockford in "JavaScript the Good Parts" described using object factories (and closures) to get rid of 'this' (OOP with Functions in JavaScript, How to decide between classes v. closures in JavaScript).