DEV Community

loading...
Cover image for 🧐Most Confusing Part Of JavaScript.

🧐Most Confusing Part Of JavaScript.

Chetan Atrawalkar👉CA.
🌈Full Stack Developer (MERN). 📝Blogger | 🎮Gamer | 👨🏻‍🏫LifeLong-Learner| 🎧Music. 🔗http://instagram.com/codev_land
・1 min read

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 when you read others code.
confused

This may be controversial, but for me it's the this keyword.

➡️ this has a different values depending on where it is used.
➡️ Inside a method this refers to the owner object.
➡️ When alone this refers to the global object.
➡️ Inside a function this
this refers to the global object too.
➡️ In a function, in strict mode this is undefined.
➡️ In a event this refers to the element that received the event.

However, since 2019 I've been using React Hooks, I haven't had to use the this keyword once.
hooks

Learn More About React Hooks On official website.
React Hooks.

Do you like React Hooks too?
Let's discuss it more in the comments section. If you agree don't forget to like ❤️ and save 📌

😎Keep Focused And Just Code It!

Discussion (29)

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
lukeshiru profile image
LUKESHIRU

I believe he mentioned React+hooks to showcase that you can have a UI without the need of this in your code, but yeah, Vue for example also moved to a composition based approach and is great as well.

Collapse
vineyrawat profile image
Viney Rawat

It's literally very easy concept 😉

Collapse
lukeshiru profile image
LUKESHIRU • Edited

Using React as an example (because Angular doesn't have a functional counterpart):

Using class and this:

class ClickCounter extends Component {
    static defaultProps = {
        initialCount = 0
    };
    constructor(props) {
        super(props);
        this.state = { count: props.initialCount };
        this.handleClick = this.handleClick.bind(this);
    }
    handleClick() {
        this.setState({ count: this.state.count + 1 });
    }
    render() {
        const { initialCount, ...props } = this.props;
        return (
            <button onClick={this.handleClick} {...props}>
                {this.state.count}
            </button>
        );
    }
}
Enter fullscreen mode Exit fullscreen mode

Using functions:

const ClickCounter = ({ initialCount = 0, ...props }) => {
    const [count, setCount] = useState(initialCount);

    return (
        <button onClick={() => setCount(count + 1)} {...props}>
            {count}
        </button>
    );
};
Enter fullscreen mode Exit fullscreen mode

IDK, but it seems that the functional approach is easier than the one with class and this. Even if we don't use React, the functional approach pretty much always will beat the class based approach in simplicity and reusability.

Cheers!

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.

Thread Thread
lukeshiru profile image
LUKESHIRU

lol bro, you wrote a lot just to say "React has internal state so it uses OOP" ... classes and OOP aren't the same thing. You can have an excellent OOP without classes, this, and all that. Besides that, even if React internally uses classes, the important thing is that us as developer using that tool don't have to. Elm internally surely has side effects, because it needs to interact with the DOM which requires mutations, but those are abstracted away thanks to the language. That doesn't make Elm less functional x'D

Thread Thread
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.

Thread Thread
lukeshiru profile image
LUKESHIRU

I mean ... Elm compiles to JS ... and the core libraries you use like Html also interact with the DOM using JS ... and doing mutations. The important thing about Elm is that it abstracts away those mutations into pure functions so that the dev isn't able to do those mutations.
React isn't an entire different language that compiles to JS (I mean, sorta because it has JSX, but is just a superset of JS like TypeScript). The thing is, that it also abstracts away the complexity of dealing with the DOM directly, and you can just use composable functions to interact with it.
You keep on mentioning closures and object instances as the same thing, but the thing is that if you use clases to create those object instances, you're basically locking away its methods inside that class, so because you really wanted to use inheritance, you ended up losing composition.
Either way, the initial point of my comment is that saying "this is a very easy concept" is kinda biased. I mean it might be easy if you have some background with class heavy languages like Java, but imagine for a second that you don't know anything about programming, in that scenario is far easier to learn how to use just functions, than having to learn about functions, classes, methods, and what is this at every point in time 🤣

Thread Thread
chetan_atrawalkar profile image
Chetan Atrawalkar👉CA. Author

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).

Collapse
lukeshiru profile image
LUKESHIRU

I agree completely! That's why I generally advocate against the use of classes and this altogether. It only makes code harder with literally no gain other than pleasing people used to classes, when nowadays we have way better alternatives to classes by just using functions.

Thanks for sharing :D

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👉CA. Author

Thanks for share your thoughts

Collapse
posandu profile image
Posandu
var var = document.querySelectorAll("*");
var.showMessage(this.crazyComment = true + "Wow It's actually confusing").Extra('Thank you for sharing' + this);
if (likecomment) {
 heartcomment();
}
else {
 removecomment();
}
Enter fullscreen mode Exit fullscreen mode

😂😉

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👉CA. Author

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
deepbb profile image
deepbb

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
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
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.

Collapse
thenerdydev profile image
The Nerdy Dev

Great article !
How did you got the highlighting on ‘this’ above ?

Collapse
chetan_atrawalkar profile image
Chetan Atrawalkar👉CA. Author

You mean this highlights

Collapse
thenerdydev profile image
The Nerdy Dev

Yep!

Thread Thread
chetan_atrawalkar profile image
Chetan Atrawalkar👉CA. Author

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👉CA. Author

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👉CA. Author

Thank for sharing