简单地聊一聊 JavaScript 中 call 和 apply 的实现

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

想要真正了解一个事物,最好方法就是自己动手实现一个,今天通过自己实现一个 call 和 apply 给大家介绍如何理解和使用 call 和 apply 来调用函数。

const tut = {
  title:"machine learning"
};

function getTitle(){
  console.log(`title: ${this.title}`)
}

getTitle.call(tut);
复制代码

定义一个对象 tut 然后在定义个函数 getTitle,直接执行getTitle() 函数,this 是指向 window 。用 call 调用函数 getTitle 就会将 this 绑定到 tut 对象上。 所以输出时候就可以用上对象属性 title

要了解 call 我们就来创建一个 call

要理解 call 方法如何使用,以及其背后到底发生了什么,最好方法就是自己去实现一个 call 方法。

const tut = {
    title:"machine learning"
}

function description(){
    console.log(`title: ${this.title}`)
}

Function.prototype.newCall = function(obj){
    console.log(this);
}

description.newCall(tut);
复制代码
index.js:10 ƒ description(){
    console.log(`title: ${this.title}`)
}
复制代码

因为这是还没有将 tut 绑定到 this,所以这时this现在还是 description 函数本身。

Function.prototype.newCall = function(obj){
    obj.tmp = this;
    obj.tmp();
    // console.log(this);
    delete obj.tmp;
}
复制代码
function description(subTitle,summay,type){
    console.log(`title: ${this.title}`);
    console.log(subTitle,summay,type);//undefined undefined undefined
}
...
description.newCall(tut,'machine learning','summary','video');
复制代码
const tut = {
    title:"machine learning"
}

function description(subTitle,summay,type){
    console.log(`title: ${this.title}`)
    console.log(subTitle,summay,type);
}

Function.prototype.newCall = function(obj){
    var obj = obj || window
    obj.tmp = this;
    var newArguments = [];
    for (let i = 1; i < arguments.length; i++) {
        newArguments.push('arguments[' + i +']');
    }
    
    console.log(newArguments)
    eval('obj.tmp(' + newArguments + ')');
    // console.log(this);
    delete obj.tmp;
}

description.newCall(null,'machine learning','summary','video');
复制代码
const tut = {
    title:"machine learning"
}

function description(subTitle,summay,type){
    // console.log(`title: ${this.title}`)
    // console.log(subTitle,summay,type);
    return {
        title:this.title,
        subTitle:subTitle,
        summay:summay,
        type:type
    }

}

Function.prototype.newCall = function(obj){
    var obj = obj || window
    obj.tmp = this;
    var newArguments = [];
    for (let i = 1; i < arguments.length; i++) {
        newArguments.push('arguments[' + i +']');
    }
    
    console.log(newArguments)
    const result = eval('obj.tmp(' + newArguments + ')');
    // console.log(this);
    delete obj.tmp;
    return result;
}

const res = description.newCall(tut,'machine learning','summary','video');
console.log(res)//{title: 'machine learning', subTitle: 'machine learning', summay: 'summary', type: 'video'}
复制代码

aplly 的实现

apply 方法与 call 比较类似,第一个参数是调用方法的对象,第二个参数是参数数组,apply 实现了 call 比较类似,我先把代码呈现在这里,大家应该一看就懂。

const tut = {
    title:"machine learning"
}

function description(subTitle,summay,type){
    console.log(`title: ${this.title}`)
    console.log(subTitle,summay,type);
    // return {
    //     title:this.title,
    //     subTitle:subTitle,
    //     summay:summay,
    //     type:type
    // }

}

Function.prototype.newApply = function(obj,arr){
    var obj = obj || window
    obj.tmp = this;
    if(!arr){
        obj.tmp()
    }else{

        var newArguments = [];
        for (let i = 0; i < arr.length; i++) {
            newArguments.push('arr[' + i +']');
        }
        
        const result = eval('obj.tmp(' + newArguments + ')');
    }
    delete obj.tmp;
}

description.newApply(tut,['machine learning','summary','video']);
复制代码

猜你喜欢

转载自juejin.im/post/7017748585370517517