Open
Description
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'
-
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 */
-
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);
-
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) }
Metadata
Assignees
Labels
No labels
Activity