Call, apply, bind
Thing in common:
-
All to solve for changing the direction of this. The function is the same, but the way the parameter is passed is different.Copy the code
Difference:
call()
和apply()
It was executed immediately, andbind()
Is to return a function.call()
Multiple arguments can be passed, the first argument andapply()
Again, is the object to replace, followed by the argument list.apply()
There can be at most two arguments — newthis
Object and an array of parameters called argArraybind()
It does the same thing as the other two methods, except that it returns a function and can be currified through bind().
Implement call() by hand
Function.prototype.call = function( context ){ // 1. Check if any object is passed to bind, no default is window; If is the basic type through the Object () method to convert the let the context = Object (context) | | window; // 2. Add a fn attribute to the context with the value this, that is, fn() // 3. Save the return value context.fn = this; let result = ''; Const args = [...arguments].slice(1); // const args = Array.prototype.slice.call(arguments , 1); // const args = Array.from(arguments).slice(1); // 5. Execute method, pass parameter //... Result = context.fn(... args); // 6. Delete the property delete context.fn; Return result; } // Test case const obj = {value :'hello'} function fn(name, age){return {value: this.value , name , age } } let res = fn.call(obj , 'LL' , 25); console.log(res) // { value: 'hello', name: 'LL', age: 25 }Copy the code
Implement apply() by hand
Function.prototype.apply = function( context , args ){ var context = Object(context) || window; context.fn = this; let result = ''; // 4. Check if the second args is passed, if the second args is passed, expand if(! Args){result = context.fn(); }else{result = context.fn(... args); } delete context.fn; return result; } // Test case const obj = {value :'hello'} function fn(name, age){return {value :this.value, name, age } } let res = fn.apply(obj ,[ 'LL' , 25]); console.log(res) // { value: 'hello', name: 'LL', age: 25 }Copy the code
Bind () by hand
Function.prototype.bind = function( context ){ // 1. Check if this is a function if(typeof this! == 'function'){throw new Error(' not a function'); } // 2. Store this const self = this; Const args1 = [...arguments]. Slice (1); args1 = [...arguments]. BindFn const bindFn = function(){const args2 = [...arguments]; Return self.apply(context, args1.concat(args2)); } return bindFn} // Test case const obj = {value :'hello'} function fn(name, age){return {value :this. age } } let res = fn.bind(obj)('HH' , 30); console.log(res)Copy the code