A, call ()

Call () makes an indirect call to a function by specifying a pointer to this, and can pass in arguments to the function call

Here’s an example:

var foo = {
    value: 1
};
function bar() { console.log(this.value) } bar.call(foo); / / 1Copy the code

First we need to know what call() does here:

  1. Specify that this points to foo
  2. Execute bar function

We can simulate these two effects:

var foo = {
    value: 1,
    bar: function() { console.log(this.value) } }; foo.bar(); / / 1Copy the code

You can see that setting bar to foo implements pointing this to foo. But doing so adds an attribute to foo for no reason, so we also need to delete it by delete. Therefore, the main implementation ideas are as follows:

// 1. Set the function to the object property foo.fn = bar // 2. Execute the function foo.fn() // 3. Delete the function from the object: delete foo.fnCopy the code

According to this idea to implement a simple version of:

Function.prototype.call2 = function(context) {// First get the function that called the call. This can get context.fn = this; context.fn(); delete context.fn; }Copy the code

Call (); call (); call (); call (); call ();

Function.prototype.call2 = function(context) { context.fn = this; var args = []; // Take the second starting argument and put it in the arrayfor(var i = 1, len = arguments.length; i < len; i++) {
        args.push('arguments[' + i + '] '); Arguments [1], arguments[2], arguments[3]] // Args automatically calls array.toString ()eval('context.fn(' + args +') ');
    delete context.fn;
}
Copy the code

Now that the core of the call() method has been implemented, we need to improve the call() function:

  1. The first argument can be passed null to indicate pointing towindow
  2. Functions can have return values

Complete implementation

Function.prototype.call2 = function(context) {
    var context = context || window;
    context.fn = this;

    var args = [];
    for(var i = 1, len = arguments.length; i < len; i++) {
        args.push('arguments[' + i + '] ');
    }
    
    var result = eval('context.fn(' + args + ') ');
    
    delete context.fn
    return result;
}
Copy the code
Var value = 2; var obj = { value: 1 }function bar(name, age) {
    console.log(this.value);
    return {
        value: this.value,
        name: name,
        age: age
    }
}
bar.call2(null); // 2
console.log(bar.call2(obj, 'kevin', 18));
// 1
// Object {
//    value: 1,
//    name: 'kevin',
//    age: 18
// }
Copy the code

Second, the apply ()

The implementation of Apply is similar to that of Call, except that the second argument to apply is passed in an array of parameters

Function.prototype.apply = function (context, arr) {
    var context = Object(context) || window;
    context.fn = this;

    var result;
    if(! arr) { result = context.fn(); }else {
        var args = [];
        for (var i = 0, len = arr.length; i < len; i++) {
            args.push('arr[' + i + '] ');
        }
        result = eval('context.fn(' + args + ') ')
    }

    delete context.fn
    return result;
}
Copy the code

At the end

Series of articles:

  • JavaScript is new from the past — prototypes and prototype chains
  • JavaScript is old and new — execution environment and scope
  • JavaScript is old and new — scoped chains and closures
  • JavaScript: 4 ways to call a function
  • JavaScript revisits the past — the implementation of call() and apply()