Why "this" Betrays You & How call/apply/bind Save Your Life – The Complete Story

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • MyrinNew
    Senior Member
    • Feb 2024
    • 5175

    #1

    Why "this" Betrays You & How call/apply/bind Save Your Life – The Complete Story

    πŸ”₯ THE ULTIMATE JS LESSON β€” this Keyword (Browser & Node)

    Greetings, fellow developers! Today, we dive into a comprehensive exploration of the this keyword and the powerful call / apply / bind methods.


    πŸš€ Repo: javascript-complete-mastery





    πŸš€ 1. What is this in JavaScript?

    this depends entirely on HOW a function is called, not where it is written.





    🧠 2. 5 Core Rules of this (Browser + Node)




    Rule 1 β€” Global Context

    Browser





    console.log(this);







    πŸ‘‰ window


    Node





    console.log(this);







    πŸ‘‰ {}





    Rule 2 β€” Function Context

    Non-strict mode





    function test() {
    console.log(this);
    }
    test();







    πŸ‘‰ Browser β†’ window

    πŸ‘‰ Node β†’ global

    Strict mode




    "use strict";
    function test() {
    console.log(this);
    }
    test();






    πŸ‘‰ undefined



    Rule 3 β€” Method Call (Object Method)

    this = object before dot






    const user = {
    name: "Usman",
    greet() {
    console.log(this.name);
    }
    };

    user.greet();







    βœ” "Usman"





    Rule 4 β€” Constructor / Class





    function Person(name) {
    this.name = name;
    }

    const p = new Person("Usman");
    console.log(p.name);







    πŸ‘‰ this refers to the new object





    Rule 5 β€” Arrow Functions (NO own this)





    const obj = {
    value: 10,
    test: () => {
    console.log(this);
    }
    };

    obj.test();







    πŸ‘‰ Browser: window

    πŸ‘‰ Node: {}



    πŸ”₯ Browser vs Node Quick Comparison

    Global context window {}
    Function (non strict) window global
    Function (strict) undefined undefined
    Method Object Object
    Arrow Parent scope Parent scope



    ⚑ 3. Deep Examples (Tricky)


    Example β€” Losing this




    const user = {
    name: "Usman",
    greet() {
    console.log(this.name);
    }
    };

    const x = user.greet;
    x();






    ❌ undefined



    Example β€” Fix with bind




    const x = user.greet.bind(user);
    x();






    βœ” "Usman"



    Arrow inside methods




    const user = {
    name: "Usman",
    greet: function () {
    setTimeout(() => {
    console.log(this.name);
    }, 100);
    }
    };

    user.greet();






    βœ” "Usman"



    Arrow in object (incorrect assumption)




    const obj = {
    a: 10,
    print: () => console.log(this.a)
    };

    obj.print();






    ❌ undefined



    🧩 Event Listeners

    Normal function




    button.addEventListener("click", function() {
    console.log(this);
    });






    πŸ‘‰ this = button element

    Arrow function




    button.addEventListener("click", () => {
    console.log(this);
    });






    πŸ‘‰ this = window



    πŸ“¦ Node.js Module Wrapper




    (function(exports, require, module, __filename, __dirname) {
    // code
    })();






    So:






    console.log(this); // {}










    πŸ“ Summary Cheat Sheet





    this = depends on how the function is called







    Browser
    • Global β†’ window
    • Function non strict β†’ window
    • Strict β†’ undefined
    • Method β†’ object
    • Arrow β†’ parent


    Node
    • Global β†’ {}
    • Function non strict β†’ global
    • Strict β†’ undefined
    • Method β†’ object
    • Arrow β†’ parent





    πŸ‹οΈβ€β™‚οΈ PRACTICE SECTION




    βœ… EASY (3)




    Problem 1





    console.log(this);







    βœ” Browser β†’ window

    βœ” Node β†’ {}



    Problem 2




    function test() {
    console.log(this);
    }
    test();






    βœ” Browser β†’ window

    βœ” Node β†’ global



    Problem 3




    const obj = {
    a: 5,
    show() {
    console.log(this.a);
    }
    };

    obj.show();






    βœ” 5



    ⚑ MEDIUM (3)


    Problem 1




    const obj = {
    a: 10,
    b: () => console.log(this.a)
    };

    obj.b();






    βœ” undefined



    Problem 2




    "use strict";

    function x() {
    console.log(this);
    }

    x();






    βœ” undefined



    Problem 3




    const user = {
    name: "Ali",
    greet() {
    setTimeout(function() {
    console.log(this.name);
    }, 0);
    }
    };

    user.greet();






    βœ” undefined



    πŸ”₯ HARD (4)


    Problem 1




    const obj = {
    name: "Usman",
    greet() {
    return () => console.log(this.name);
    }
    };

    const x = obj.greet();
    x();






    βœ” "Usman"



    Problem 2




    class A {
    constructor() {
    this.num = 100;
    }

    show() {
    console.log(this.num);
    }
    }

    const a = new A();
    const s = a.show;
    s();






    βœ” undefined



    Problem 3




    const obj = {
    x: 15,
    y: {
    z: function() {
    console.log(this.x);
    }
    }
    };

    obj.y.z();






    βœ” undefined



    Problem 4




    let a = {
    value: 50,
    print: function() {
    (function() {
    console.log(this.value);
    })();
    }
    };

    a.print();






    βœ” undefined



    πŸš€ THE ULTIMATE JS LESSON β€” call(), apply(), bind()

    JavaScript gives us three powerful methods to manually control the value of this inside a function.

    These are essential for interview questions, real-world bug fixing, and writing professional code.



    πŸ”₯ 1. Why do we need call/apply/bind?

    Because sometimes, a function loses its this:






    function greet() {
    console.log(this.name);
    }

    const user = { name: "Usman" };

    greet(); // ❌ undefined







    We want to run greet with this = user.


    That’s where these methods come in.





    🧠 2. call() β€” calls the function immediately





    func.call(thisValue, arg1, arg2, ...)







    Example





    function greet(age) {
    console.log(this.name, age);
    }

    const user = { name: "Usman" };

    greet.call(user, 22);







    βœ” Sets this = user

    βœ” Executes immediately

    βœ” Arguments passed one-by-one





    🧠 3. apply() β€” same as call, but arguments in an array





    func.apply(thisValue, [arg1, arg2, ...])







    Example





    greet.apply(user, [22]);







    βœ” Same output

    βœ” Just a different argument format





    🧠 4. bind() β€” returns a NEW function with fixed this





    const newFn = func.bind(thisValue, arg1, arg2);







    Example





    const greetUser = greet.bind(user, 22);
    greetUser();







    βœ” Does NOT run immediately

    βœ” Creates a new function with permanent this





    πŸ”‘ 5. The Three in One Line





    call β†’ call immediately (args individually)
    apply β†’ call immediately (args in array)
    bind β†’ return new function (does NOT run)










    πŸ“¦ 6. Real-world Uses

    βœ” Borrowing methods





    let obj1 = { name: "Ali" };
    let obj2 = { name: "Usman" };

    function sayHi() {
    console.log("Hi " + this.name);
    }

    sayHi.call(obj2);










    βœ” Using Array methods on non-arrays





    const nums = {
    0: 4,
    1: 8,
    length: 2
    };

    console.log(Array.prototype.join.call(nums, "-"));










    βœ” Fixing this in event handlers





    button.addEventListener("click", obj.method.bind(obj));










    βœ” Currying with bind





    function multiply(a, b) {
    return a * b;
    }

    const double = multiply.bind(null, 2);
    console.log(double(5)); // 10










    🧨 7. Tricky & Important Behaviors




    ❗ Arrow functions IGNORE call/apply/bind





    const obj = { a: 10 };

    const x = () => console.log(this.a);
    x.call(obj); // ❌ still not obj







    Arrow functions use lexical this, so you cannot change it.





    ❗ bind creates a new function (original stays unchanged)





    function a() {}
    const b = a.bind({});
    console.log(a === b); // false










    ❗ Multiple binds β†’ first one wins





    const x = greet.bind(obj1).bind(obj2);
    x(); // uses obj1










    ⚑ 8. Browser vs Node?

    No difference in behavior.


    call/apply/bind work the same in both.

    Only the default this differs, not these methods.





    🧩 9. Practice Problems




    βœ… EASY (3 Problems)




    Problem 1 β€” Output?





    function say() {
    console.log(this.x);
    }

    const obj = { x: 10 };

    say.call(obj);







    Solution





    10










    Problem 2 β€” Output?





    function sum(a, b) {
    console.log(a + b);
    }

    sum.apply(null, [5, 7]);







    Solution





    12










    Problem 3 β€” Output?





    function greet(name) {
    console.log("Hi " + name);
    }

    const g = greet.bind(null, "Usman");
    g();







    Solution





    Hi Usman










    ⚑ MEDIUM (3 Problems)




    Problem 1 β€” Output?





    const user = {
    name: "Ali",
    say() {
    console.log(this.name);
    }
    };

    const fn = user.say;
    fn.call(user);







    Solution





    Ali










    Problem 2 β€” Output?





    function add(a, b) {
    console.log(this.x + a + b);
    }

    const obj = { x: 5 };

    add.call(obj, 10, 15);







    Solution





    30










    Problem 3 β€” Output?





    function intro(age, country) {
    console.log(this.name, age, country);
    }

    const p = { name: "Usman" };

    intro.apply(p, [22, "PK"]);







    Solution





    Usman 22 PK










    πŸ”₯ HARD (4 Problems)




    Problem 1 β€” Output?





    const a = { value: 50 };

    function print() {
    console.log(this.value);
    }

    const b = print.bind(a);
    b.call({ value: 100 });







    Solution





    50










    Problem 2 β€” Output?





    const obj = {
    x: 10,
    y: function() {
    console.log(this.x);
    }
    };

    const z = obj.y.bind({ x: 99 });
    z();







    Solution





    99










    Problem 3 β€” Output?





    function show() {
    console.log(this.a);
    }

    const o1 = { a: 1 };
    const o2 = { a: 2 };

    const f = show.bind(o1);
    f.call(o2);







    Solution





    1










    Problem 4 β€” Output?





    function multiply(a, b, c) {
    console.log(a * b * c);
    }

    const f = multiply.bind(null, 2);
    f.apply(null, [3, 4]);







    Solution





    24










    Congratulations on mastering this, call(), apply(), and bind()! To further enhance your JavaScript journey, I’ve developed a free, structured repository featuring topic-by-topic training, ranging from beginner to advanced levels, organized into a 42-day mastery plan. Completing this resource will significantly ease your transition into frameworks and stacks like React, Node, and Next.js.

    πŸš€javascript-complete-mastery




    More...
Working...