Interview---js realizes call and apply, bind

Both call and apply modify the method pointed to by this.
Let's start with a simple use

	var foo = {
    
    
        value: 1
    };
    function bar(name, age) {
    
    
        console.log(name,age,this.value)
    }
    bar.apply(foo,['kevin', 18]);   //kevin 18 1
    
    var foo = {
    
    
        value: 1
    };
    function bar(name, age) {
    
    
        console.log(name,age,this.value)
    }
    bar.call(foo,'kevin', 18); //kevin 18 1

The only difference in usage is passing parameters. The call needs to pass in the parameters one by one, and the apply parameter is passed in as an array.
Let's implement the call method
. Imagine how to make bar belong to foo. Because only when bar enters foo, this points to foo
. Friends can definitely think of it, add the method to foo and execute it, and then delete it after execution.

Function.prototype.call2 = function(context){
    
    
        context.fn = this;
		context.fn();
        delete context.fn;
 }
//我们在测试一下
	var foo = {
    
    
        value: 1
    };
    function bar() {
    
    
        console.log(this.value);
    }
    bar.call2(foo);   // 1

1 is printed here, and it is realized. ( )
Don't be too anxious to be happy, there are other needs to be fulfilled.
call defaults to window when no target object is passed in. There is also the case of carrying parameters.
So let's optimize

	Function.prototype.call2 = function(context){
    
    
        var context = context || window;
        context.fn = this;
        let arr = [];
        for(let i = 1,len = arguments.length; i < len; i++ ){
    
    
            arr.push(arguments[i]);
        }
        context.fn(...arr);
        console.log(context.fn)
        delete context.fn;
    }
	//下面是简化版
	Function.prototype.call3 = function(context){
    
    
		var context = context || window;
		context.fn = this;
		var arr = Array.prototype.slice.call(arguments,1);
		context.fn(...arr);
		delete context.fn;
	}
	
    //下面是测试
    var foo = {
    
    
        value: 1
    };
    function bar(name, age) {
    
    
       console.log(name,age,this.value)
    }
    bar.call2(foo, 'kevin', 18); //kevin 18 1

We first made a judgment above, judging whether the target parameter exists, and does not point to window.
Get the passed parameters into the array. There is another knowledge point here, which is arguments. (Accept all parameters passed in); we put all the parameters except the first parameter into the array, and then pass it in when calling. My side is using es6 method.
Some other big guys use eval('context.fn(' + args +')'); this way of writing. Execute the delete method.
In this way, we have implemented a call method.
The following is the code to implement apply. The principle is the same and I won’t say more.

	Function.prototype.apply2 = function(context,arr){
    
    
        var context = context || window;
        context.fn = this;
        context.fn(...arr);
        delete context.fn;
    }
    var foo = {
    
    
        value: 1
    };
    function bar(name, age) {
    
    
        console.log(name)
        console.log(age)
        console.log(this.value);
    }
    bar.apply2(foo,['kevin', 18]); 

The implementation of bind
Let's take a look at the simple usage of bind first.

	let obj = {
    
    
        value:1
    }
    function d(name){
    
    
        console.log(this.value)
        console.log(name);
    }

    var y = d.bind(obj,'lly')
    y() 
    //1
    //lly

You can see above that bind returns a function and can accept a parameter.
Let’s see how to achieve this

	Function.prototype.bind2 = function(context){
    
    
        var self = this;
        var arge = Array.prototype.slice.call(arguments,1);   //取出接受除去第一个的参数数组
        var funone = function(){
    
    
           return self.apply(context,arge)    //通过apply来修改this
        }
        return funone
    }

From the above content, we can see that bind2 returns a function and passes the accepted parameters.
bind has another situation to see the code

	let obj = {
    
    
            value:1
        }
        function d(name,age){
    
    
            console.log(this.value);
            console.log(name)
            console.log(age)
        }

        var y = d.bind2(obj,'lly')
        y(20)   //1 'lly' 20

In the above code, we can see that this bind can not only pass parameters when binding, but also pass parameters when calling.
This is also easy to implement. Let's look at the code

Function.prototype.bind2 = function(context){
    
    
        var self = this;
        var arge = Array.prototype.slice.call(arguments,1);   //取出接受除去第一个的参数数组
        var funone = function(){
    
    
            let arr = Array.prototype.slice.call(arguments);
           return self.apply(context,arge.concat(arr))    //通过apply来修改this
        }
        return funone
    }

concat (merge two arrays together)
we can see that we only need to accept the parameters again when creating the function. It’s good to put it together when it’s passed in.
Next, let’s look at another piece of code. Another usage of bind is put back when the function is used as a constructor.

		var value = 2;
        let obj = {
    
    
            value:1
        }
        function d(name,age){
    
    
            console.log(this.value)
            console.log(name)
            console.log(age)
        }
        var y = d.bind(obj,'lly');
        let as = new y(20);
        //undefind  lly 20

At this time, we can see that the value inside cannot be found. At this time, this no longer belongs to obj. This is because of that, think about what the process of new does. (Students who don’t know have a look, click here to have a look ) You can also look at other people’s better written ones. This process has already pointed to this object of the new new. So our global value can't be found either. The this bound by bind can't be found either. But the parameters passed in are still in effect. The following is to realize the situation when the constructor of the object is used.

	 Function.prototype.bind2 = function(context){
    
    
        var self = this;
        var arge = Array.prototype.slice.call(arguments,1);   //取出接受除去第一个的参数数组
        let funa = function(){
    
    };
        var funone = function(){
    
    
            let arr = Array.prototype.slice.call(arguments);
           return self.apply(this instanceof self?this:context,arge.concat(arr))    //通过apply来修改this
        }
        funa.prototype = this.prototype;
        funone.prototype = new funa();
        return funone
    }

	

Reference
https://juejin.cn/post/6844903476477034510#heading-2
https://juejin.cn/post/6844903476623835149

Guess you like

Origin blog.csdn.net/weixin_44655037/article/details/117127573