Handwritten apply call bind implementation

apply call bind related

For apply call bind, I also wrote a very detailed entry-level article before apply, call, bind usage and differences

After understanding the usage, it is better to understand its implementation principle so that you can grasp it thoroughly

The difference between the three

  1. callAnd applythey are made to address changing thispoints. The effect is the same, but the way of passing parameters is different
  2. In addition to the first parameter, callyou can receive a list of parameters, and applyonly accept an array of parameters
  3. bindThe effect is the same as the other two methods, except that the method returns a function. Will not be executed immediately

Handwritten call

  • Handle the needs:

    • Change this point. Point to window by default
    • Can receive multiple parameters
    • Execute the method after changing this request
    • All methods mount this myCall
  • Analyze the realization ideas:

    • For this. Just remember that whoever calls the method, this will point to (except for arrow functions), and let the object/window passed in to call the method.
    • Receive multiple parameters: argumentsor es6 new syntax:...args
    • Execute the function immediately, sprinkle water
    • All methods are mounted, then the prototype chain is used, mounted on the Functionobject
  • Everything is ready, start to achieve:

Function.prototype.myCall = function(context, ...args) {
    
    
  // 默认的window对象
  context = context && typeof context === 'object' ? context : window
  // 防止覆盖掉原有属性
  const key = Symbol()
  // 这里的this为需要执行的方法
  context[key] = this
  // 方法执行
  const result = context[key](...args)
  delete context[key]
  return result
}
  • Summarize the implementation
    • First, make sure that the new pointer is an object type object. Otherwise, all are windows by default. Of course, typeof null is also equal to "object". So we have to use a judgment to ensure that the context exists
    • SymbolRole: to prevent conflicts of attribute names. Why do you want to do this? Because we need to put a property on the new object, this property is the old one this. But how to ensure that new properties and not contextthe original attributes conflict it? Then useSymbol
    • It might be above context[key] = thisdoubt. This is why in the end, why should the new contextrelease of this old object? There will be code explanation principles later
    • There is no problem with the execution method~
    • Finally deleteout our new property, after all, can not affect the original contexttarget

What is the small expansion context[key] = this?

Understanding context[key] = thishas a very important significance for the entire handwritten code implementation

First of all, the principle that has remained unchanged for thousands of years: whoever calls a method, this points to whom.
Then why not contextcall the corresponding method?
Because contextbasically there is no corresponding method

Use a small example to understand the problem

let data = {
    
    
  key: 1,
  name: 'Jioho',
  say: function() {
    
    
    console.log(this.name)
  }
}
function fn() {
    
    
  console.log(this.name)
}

data.say() // Jioho
fn() // 打印为空

// 那如果这样:
data.sayfn = fn
data.sayfn() // Jioho
  • Gap appeared, as long as the corresponding method in which an object, the method will be able to get the current thisinstance
  • context[key] = thisThe same is true. This time thisis the original function this. The this in the original function has its own method. So we directly assign the entire this to context. Just like the 16th line of the code above
  • As we start keywhy Symbol. It's just that we are afraid of the same name if our 16th new attribute is not called sayfn. Called say, then our subsequent operations will affect the properties of the original object. This is a problem that must not arise!

Handwriting apply

If handwriting call after understanding apply just a question pass Senate

The rest of the code does not need to be changed, just need to be an array type when receiving the second parameter

Function.prototype.myApply = function(context, args = []) {
    
    
  // 默认的window对象
  context = context && typeof context === 'object' ? context : window
  // 防止覆盖掉原有属性
  const key = Symbol()
  // 这里的this为需要执行的方法
  context[key] = this
  // 方法执行
  const result = context[key](...args)
  delete context[key]
  return result
}

Handwriting bind

  • Handle the needs:

    • Change this point. Point to window by default
    • Parameters before calling bind, you can pass in multiple
    • In the returned function, you can continue to pass parameters. This scene is still very practical
    • All methods mount this myBind
  • Analyze the realization ideas:

    • No need to change this point on to say, whether it is handwritten achieve, or use the original applyor callwill do
    • Can pass multiple parameters before calling bind, it is still used argumentsor ...argsunified received
    • bind needs to return one 函数. And you can continue to pass parameters in the new function, then you need to use closures
    • All methods are mounted, then the prototype chain is used, mounted on the Functionobject
Function.prototype.myBind = function(context, ...args) {
    
    
  context = context && typeof context === 'object' ? context : window
  const _self = this
  return function(...args2) {
    
    
    return _self.apply(context, [...args, ...args2])
  }
}

// 接下来验证一下:
var data = {
    
     baseCount: 10 }
function add(num1, num2) {
    
    
  return this.baseCount + num1 + num2
}

// 调用方法
var addBind = add.myBind(data, 1)
addBind(2) // 13

// 或者这样写
add.myBind(data, 1)(2) // 13
  • Summarize the implementation
    • The same years contextto achieve
    • Because there are ways to receive a plurality of parameters two times, we used ...argsto receive also must be an array of. So it’s most appropriate to use apply in the returned function.

Don't underestimate the seemingly weird way of writing bind. Why do you have to pass the parameter twice? When we talk about complex currying later, we will discover the charm of bind now.

The original post was published in: apply call bind related new blog address, if you are interested, you can check it out~

Guess you like

Origin blog.csdn.net/Jioho_chen/article/details/107011523