Implementation of apply()

Get into the habit of writing together! This is the 9th day of my participation in the "Nuggets Daily New Plan · April Update Challenge", click to view the details of the event .

foreword

Yesterday, I wrote an implementation of call() by hand. You can click the link to view the specific content . Today, I will write the implementation of apply() to deepen my memory.

apply() and call()

Before writing apply(), I have to mention the relationship between apply and call. They both have similarities and differences.

  • common ground
  1. They can both change the point of this
  2. can pass parameters to the target function
  • difference
  1. Their parameter forms are different

Based on the above differences and similarities, we can easily draw the conclusion that the main difference between the handwritten code of apply and the handwritten code of call should be in the handling of passed parameters. First of all apply we have specified the number of its parameters, then we don't need to use arguments. See the code below

    Function.prototype.myApply= function(context,arr){
            context = context || window
            context.fn = this
            var result;
            if(!arr){
                result = context.fn()
            }else{
                var args = []
                for(var i=0;i<arr.length;i++){
                    args.push(arr[i])
                }
                result = context.fn(...args)
            }
            delete context.fn
            return result
        }
复制代码

Note: The above code directly uses the spread operator in es6. If it is required not to use es6, then you can also use the eval() function like the implementation of call ( eval('context.fn(' + args +')') ). Test it below to see if there is any problem. First test whether the pointing of this has changed

 animal = {color:'yellow'}
        function dog(){
            console.log(this.color)
        }
        console.log(dog.myApply(animal))
复制代码

The result is as follows

image.png

The this point has been successfully changed. Let's test whether there is a problem with passing parameters.

animal = {color:'yellow'}
        function dog(name,age){
            
            console.log(this.color)
            console.log(name)
            console.log(age)
            return {
                name:name,
                age,age,
                color:this.color
            }
        }
        console.log(dog.myApply(animal,['小白',6]))
复制代码

The result is as follows

image.png

The parameters passed in are successfully printed out, indicating that the main functions of apply are basically realized.

Summarize

The implementation logic of call() and apply() is actually similar. The main difference is the type and number of parameters when they are used. But in fact, there are still some problems with the above implementation.

  1. The fn in the code is that we assume that the context does not have this property. If the context already has this property, there will be a problem (the solution here can use var fn = Symbol() ) But it uses the features of es6, if If you don't want to use it like this, write a combination of random number and fn, and then judge whether the context contains this field. If it does, it will be regenerated until it does not have this attribute.

2. The incoming context may not be an object (one can be a basic data type, such as string). At this time, we need to deal with the context, then context= Object(context) || window, this is perfect.

Guess you like

Origin juejin.im/post/7086742049067630606