Usage and implementation of apply call bind

Keywords: Javascript Attribute

concept

apply call and bind allow assignment and invocation of functions/methods belonging to one object for different objects.They can also change the direction of this within the function.

Difference

  • apply and call receive parameters in different forms

  • Both apply and call call call call functions directly and get the result of their execution, while bind returns the function to be executed and needs to be called again

Usage demonstration

Let's first create an object parent

const parent = {
    name: 'parent',
    sayPerson (age, addr) {
        return {
            name: this.name,
            age,
            addr
        }
    }
}

Obviously it has the name attribute and the method sayPerson, which we can now output through parent.sayPerson().

const person = parent.sayPerson(60, 'shenzhen');
// {name: "parent", age: 60, addr: "shenzhen"}

Now let's create another object, son

const son = {
    name: 'son'
}

We also want information about son now, but what if the son object does not have the sayPerson function?With the existing parent object and call method, we can write

const person = parent.sayPerson.call(son, 26, 'shenzhen');
// {name: "son", age: 26, addr: "shenzhen"}

As you can see, by calling the call function, we assign and call the sayPerson method to the son object.Implements an object that can call a method that does not belong to it, and this within the function points to the object.The apply method is actually used the same way, but there are some differences in passing parameters

const person = parent.sayPerson.call(son, [26, 'shenzhen']);
// {name: "son", age: 26, addr: "shenzhen"}

Instead of calling the function directly, the bind function returns the function to be called

const sayPersonFn = parent.sayPerson.bind(son, 26, 'shenzhen');

const person = sayPersonFn();
// {name: "son", age: 26, addr: "shenzhen"}

That's how they work and how they differ. Let's see how they work

Realization

Implementation of call

The idea is to add the method you need to call for the object obj, then call it (where this points to obj), then delete the method after the call

Simple Edition

Object.prototype.callFn = function (...args) {
    // The first parameter is the target object
    const context = args[0];

    args.shift();

    // Assigning an object to a method that needs to be called
    context.fn = this;

    // Call this method
    context.fn(...args);

    // Delete Method
    delete context.fn;
}

Add Return Value

Object.prototype.callFn = function (...args) {
    // The first parameter is the target object
    const context = args[0];

    args.shift();

    // Assigning an object to a method that needs to be called
    context.fn = this;

    // Call this method
    const result = context.fn(...args);

    // Delete Method
    delete context.fn;

    return result;
}

In the test, we found that we called call, and if the first parameter is null or undefined, the call will call the method with the global window, where this also points to the window.If the first parameter is not an object type, the method is called with an empty object {}.

Object.prototype.callFn = function (...args) {
    // The first parameter is the target object
    let context = args[0];

    // undefined and null point to window
    if (context === null || context === undefined) {
        context = window;
    }

    // Create an empty object if it is not an object type
    if (typeof context !== 'object') {
        context = {};
    }

    args.shift();

    // Assigning an object to a method that needs to be called
    context.fn = this;

    // Call this method
    const result = context.fn(...args);

    // Delete Method
    delete context.fn;
    
    return result;
}

So far, we have implemented a complete call method.

Implementation of apply

Since there is only a parameter difference between call and call, we only need to modify the implemented call method.

Object.prototype.applyFn = function (...args) {
    let context = args[0];

    if (context === null || context === undefined) {
        context = window;
    }

    if (typeof context !== 'object') {
        context = {};
    }

    args.shift();

    context.fn = this;

    // What's different from call
    const result = context.fn(...args[0]);

    delete context.fn;

    return result;
}

Implementation of bind

On the premise of implementing apply and call, the implementation of bind is relatively simple.

Object.prototype.bindFn = function (...args) {
    // The reality is that there are multiple bundled layers of functions to execute
    return () => {
        return this.applyFn(args[0], (args || []).slice(1));
    }
}

For problems with creating objects using functions returned by the bind method as constructors, see Simulated implementation of JavaScript in-depth bind.

summary

call apply bind is actually a more common function in your work, especially in the source code of some frameworks or libraries, but their usage is often confused.I hope you can thoroughly understand their roles and differences through this article, and know how they work, and why they work.

Reference resources

Welcome to Front End Learning Card Group to study together~516913974

Posted by rckehoe on Mon, 11 May 2020 16:53:17 -0700