contrast

1. call/apply

  1. The first argument is the changed THIS reference, which is written to whoever it is (special: in non-strict mode, passednull/undefinedIt also points to window.
  2. The only difference: the way functions are executed, the way arguments are passed,callIs passed on one by one,applyPass the parameters in an array as a whole
func.call([context],10.20) 
func.apply([context],[10.20])
Copy the code

2. bind

  1. call/applyBind changes this and executes the function directly, whereas bind does not execute the function immediately.
  2. In addition, additional parameters can be passed at binding time, and additional parameters can be passed at execution time.

call

  1. When the first parameter is null or undefined, this refers to the global object Window, and the primitive value refers to the auto-wrapped object of the primitive value, such as String, Number, or Boolean
  2. To avoid conflicts between function names and attributes of the context, use the Symbol type as the unique value
  3. The function is executed as a context property passed in
  4. Delete this property after the function completes execution
  5. Return execution result
function add(c, d) {
  return this.a + this.b + c + d;
}
const obj = { a: 1.b: 2 };

function es6call(context, ... args) {
	context = context || window / / 1.
	context === null ? context = window : null;
	let type = typeof context;
	if(type ! = ="object"&& type ! = ="function"&& type ! = ="symbol") {
		//=> Indicates that it is not a reference type but a basic type value
		switch (type) {
			case 'number':
				context = new Number(context);
				break;
			case 'string':
				context = new String(context);
				break;
			case 'boolean':
				context = new Boolean(context);
				break; }}let $fn = Symbol(a)// 2. Create a unique Symbol variable to avoid duplication
	context.$fn = this;// this = the function add that needs to be executed
	args = args ? args : []
	$fn is called as an object call, in which case this refers to the context
	let result = args.length > 0? context.$fn(... args) : context.$fn();// 3. Execute context.$fn(), which is the function add to be executed, and pass in the argument, in which case this refers to context
	delete context.$fn; / / 4.
	returnresult; ,,,5. 
} 
		
console.log(add.es6call(obj, 3.4)); / / 10
Copy the code
  • It is also possible to write methods on the prototype of function
Function.prototype.myCall = function((context, ... args){}Copy the code

apply

  1. The former part is the same as call
  2. The second argument may not be passed, but the type must be array or array-like
function apply(context = window, args) {
        context.$fn = this;
        letresult = context.$fn(... args);delete context.$fn;
        return result;
}

Copy the code

bind

  1. Need to consider:
    • Bind () can pass multiple arguments in addition to this;
    • New functions created by bind may pass in multiple arguments;
    • New functions may be called as constructors;
    • A function may have a return value;
  2. Implementation method:
    • The bind method does not execute immediately and needs to return a function to be executed; (closures)
    • Implement scope binding (apply)
    • Parameter passing (array passing for apply)
    • When used as a constructor, stereotype inheritance is performed
 ~ function anonymous(proto) {
    function bind(context){
                //=>this: the function to be executed
                //context may be null or undefined
                if (context == undefined) {
                        context = window;
                }
                // Get the collection of arguments passed
                / / the arguments {0: context, ", ", length: 3} incoming the arguments is an array class. Not a real array, so you can't use the slice method of an array
                var args = [].slice.call(arguments.1) // equivalent to arguments.slice, gets the collection of arguments passed
                // The function that needs to be executed finally
                var  _this = this //obj.fn

                function anonymous(){ 
                        var innerArg = [].slice.call(arguments.0) // Accept the parameters passed in when anonymous is executed. We cut it off at 0.
                        args = args.concat(innerArg) // Concatenate two arrays
                        // If this of the current function refers to this in the constructor, it is considered new
                        var new_this = this instanceof _this ? this : context
                        _this.apply(new_this, args)
                }
         // To complete the new operation, there is one more thing you need to do to perform the prototype link
                 // Maintain prototype relationships
                var fnNoop = function(){} / / empty function
                if(this.prototype){
                        fnNoop.prototype = this.prototype
                }
                anonymous.prototype = new fnNoop()
                return anonymous
    }
    proto.bind = bind


 }(Function.prototype)

Copy the code