This article has participated in the activity of “New person creation Ceremony”, and started the road of digging gold creation together.

preface

In another year of crazy handwriting, let’s implement the Apply function in JavaScript.

I. Sorting out ideas

Before implementing handwritten Apply, let’s review the use scenarios of the Apply function. Usually when we use Apply, we need two objects (everything is an object 🙈) :

  1. The function you want to implement (let’s say foo).
  2. We want to be able to call foo’s object (let’s say obj).

So the main breakthrough when we implement apply is to be able to get foo and obj. So let’s implement the Apply method with this idea in mind.

Second, the implementation of apply method

function jApply(thisArg, argArray = []) {
  // This points to window when null and undefined are passed in
  thisArg = thisArg ?? window

  // Make sure that Object is passed in
  thisArg = Object(thisArg)

  // Generate a unique key to avoid duplicating the key of the passed object
  const key = Symbol()
  thisArg[key] = this

  // Get the execution result of the function
  constresult = thisArg[key](... argArray)// Remove the manually added attributes to make thisArg back to its original appearance
  delete obj[key]

  // Returns the result of the function's execution
  return result
}

Function.prototype.jApply = jApply
Copy the code

3. Display of test results

function foo(x, y, z) {
  console.log(x + y + z, this);
}

const obj = {
  name: 'ZJoker',}const numArr = [1.2.3]

foo.jApply()
foo.jApply(null,numArr)
foo.jApply(undefined,numArr)
foo.jApply(123,numArr)
foo.jApply('123',numArr)
foo.jApply(false,numArr)
foo.jApply([],numArr)
foo.jApply({},numArr)

console.log('--------- I'm divider ----------');

foo.apply()
foo.apply(null,numArr)
foo.apply(undefined,numArr)
foo.apply(123,numArr)
foo.apply('123',numArr)
foo.apply(false,numArr)
foo.apply([],numArr)
foo.apply({},numArr)
Copy the code

Four, the implementation of detailed explanation

4.1 Get the object to call the target function

  // This points to window when null and undefined are passed in
  thisArg = thisArg ?? window

  // Make sure that Object is passed in
  thisArg = Object(thisArg)
Copy the code

ThisArg = thisArg = thisArg; thisArg = thisArg; thisArg = thisArg; thisArg = thisArg; thisArg = thisArg

However, we have no control over whether arguments are passed or what type of the first argument is passed when using apply, so we manually process the arguments passed down.

4.2 Getting the target function to be called

  // Generate a unique key to avoid duplicating the key of the passed object
  const key = Symbol()
  thisArg[key] = this
Copy the code

Normally we use the apply method in xxx.apply() mode, so the execution of apply is invoked by foo. That is, this inside apply refers to our target function foo.

At this point we have fully retrieved the target function foo and the target object obj. But there’s a boundary case that we have to deal with.

To be able to make obj (parameter thisArg) call our foo, we bind foo’s this to obj (the actual meaning of the apply method, changing the function’s this pointer). We need to execute the target function as obj.foo(). So let’s add a new method to obj which is our foo. However, how to name key is a problem worth considering. We want to avoid the same name as obJ’s original method, so Symbol is used here to ensure the uniqueness of key value.

4.3 Obtaining the target function parameter

  // Get the execution result of the function
  constresult = thisArg[key](... argArray)// Remove the manually added attributes to make thisArg back to its original appearance
  delete obj[key]

  // Returns the result of the function's execution
  return result
Copy the code

Normally our foo might have its own arguments, so in the apply method, we pass the second iterable argument to Foo using the expansion syntax as the argument foo needs.

Here we use the concept of Spread syntax in ES6 to pass the second argument (argArray) to the target function foo in the following line of code… argArray

thisArg[key](... argArray)Copy the code

Finally we remove the method foo that was manually added to obj, make thisArg back to its original appearance, and return the execution result of obj.foo().

conclusion

The above is the implementation process of handwritten Apply, a learning record from JS Xiaobai, welcome to correct the wrong place.

————— I’m the splitter —————

Concise code, detailed explanation, each front-end ER will be able to handwritten bind method.

Concise code, detailed explanation, each front-end ER will be able to handwritten apply method.

Concise code, detailed explanation, each front-end ER should be able to handwritten call method