Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A brief introduction of Call, Apply, Bind #30

Open
cheatsheet1999 opened this issue Sep 10, 2021 · 0 comments
Open

A brief introduction of Call, Apply, Bind #30

cheatsheet1999 opened this issue Sep 10, 2021 · 0 comments

Comments

@cheatsheet1999
Copy link
Owner

Call, Apply, Bind

  • Common
    • They all used to redirect 'this' keywords
  • Difference
    • call & apply will invoke the function, and modify 'this'
    • call passes arg1, arg2... apply passes an array [arg]
    • bind does not invoke a function
  • In practice
    • call is used on inheritance, 'this' in the 'father' class will point to 'son' class
    • apply can work with array, such as seeking for max and min
    • bind will not call the function, and is also able to redirect 'this'
  1. call

    It works in two ways, first, it could be used to call a function. Second, we can use it to redirect "this" in a function

    In some cases, call could be used for inheritance

    fun.call(thisArg, arg1, arg2, ...)
    let o = {
      name: 'andy'
    }
    
    //1. "this" in fn function originally point to the window object, but I want it to point to "o" object
    function fn(a, b) {
      console.log(this);
      console.log(a + b);
    }
    
    fn.call(o, 1, 2) //now fn is pointing to o, and pass two parameters
    
    function Father (uname, age, gender) {
      this.uname = uname;
      this.age = age;
      this.gender = gender;
    }
    
    //Call Father, and change this 
    function Son(uname, age, gender) {
      //Now "this" is pointing to to this function(Son).
      //It implicitly copies this.uname = uname age.... gender...;
      Father.call(this, uname, age, gender)
    }
    
    //Thus, we can use
    let son = new Son('Morty', 18, 'male');
    console.log(son);
    /* Above log outputs:
    Son:
    	age: 18
    	gender: male
    	uname: Morty
    */
  2. apply

    it also calls a function, and modify 'this'

    One of the big advantages is we can coordinate apply with some built-in function, such as Math.max()

    fun.apply(thisArg, [argsArray])
    • thisArg: "this" will point to the place where we desired
    • argsArray: the values we want to pass must contain in an array (at least, it looks like an array...)
    let o = {
      name: 'andy'
    }
    
    function fn(arr) {
      console.log(this);
      console.log(arr);
    }
    
    //we want fn point to "o" object, so
    fn.apply(o, ['morty']);
    /*above line outputs
    	Object, 
    	morty
    */
    
    let arr = [1, 66, 3, 99, 4];
    //null means we don't need to modify "this", but probably not working in strict mode, so I used Math to work around.
    let max = Math.max.apply(Math, arr);
  3. bind

    bind will NOT invoke the function, but it can change 'this' direction

    If we want to modify 'this' direction without invoking the function, then bind is the way to go

    fun.bind(thisArg, arg1, arg2, ...);
    let o = {
      name: 'andy'
    }
    
    function fn(a, b) {
      console.log(this);
      console.log(a + b);
    }
    //remember bind wouldn't invoke function
    fn.bind(o);
    //one way to work around
    let f = fn.bind(o, 1, 2);
    f();
    //it returned a new function after "this" has been changed from original function
    

    Example: if we have a button, after clicking it, the button will be disabled. After 3 seconds, the button is enabled. (Send message verification code in web apps)

    1st edition

    let btn = document.querySelector('button');
    btn.onclick = function() {
      //this point to itself => btn
      this.disabled = true;
      setTimeout(function() {
        //'this' point to window, becuase it is a timer function, and window does not have disabled attribute
        this.disabled = false;
      }, 3000)
    }

    2nd edition 🟡

    let btn = document.querySelector('button');
    btn.onclick = function() {
      //this point to itself => btn
      this.disabled = true;
      //works fine
      let that = this;
     
      setTimeout(function() {
        that.disabled = false;
      }, 3000)
    }

    3nd edition ✅

    let btn = document.querySelector('button');
    btn.onclick = function() {
      //this point to itself => btn
      this.disabled = true;
      setTimeout(function() {
        this.disabled = false;
        //the bind is out of timer function, but inside onclick, so it also points to btn, bind to btn, 'this' points to btn not
      }.bind(this), 3000)
    }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant