聊一聊bind、call与apply 的区别及实现

214 阅读1分钟

这三个方法的区别

首先说下bind与call的区别 call和apply都是为了解决改变this的指向。它们的作用是相同的。只是他们传的参数的方式不同。第一个参数都是要指向的对象。apply的第二个参数为要传递的参数数组,而call则是将这个数组进行拆分为第二、第三、第四、...、第N个参数传递。

let student = {
    name: '小明'
};
function getStudentInfo(age, height) {
    console.log('年龄' + age);
    console.log('身高' + height);
    console.log('姓名' + student.name);
};
getStudentInfo.call(student, 24, '178cm');
getStudentInfo.apply(student, [24, '178cm'])

// 运行后的结果
年龄24
身高178cm
姓名小明
年龄24
身高178cm
姓名小明

至于bind方法,他是直接改变这个函数的this指向并且返回一个新的函数,不是直接调用立刻执行,之后再次调用这个函数的时候this都是指向bind绑定的第一个参数。bind传餐方式跟call方法一致。

如何在es3中自己实现bind函数

if (!Function.prototype.bind) {
    Function.prototype.bind = function () {
        var self = this,                        // 保存原函数
        context = [].shift.call(arguments),     // 保存需要绑定的this上下文
        let args = [].slice.call(arguments);    // 剩余的参数转为数组
        return function () {                    // 返回一个新函数
            self.apply(context,args);
        }
    }
}

如何自己实现call函数

Function.prototype.myCall = function(context) {
    context.fn = this;
    let args = [...arguments].slice(1);
    let result = context.fn(...args);
    delete context.fn
    return result
}

如何自己实现apply函数

Function.prototype.myApply = function(context) {
    context.fn = this;
    let args = arguments[1];
    if (Object.prototype.toString.call(args).slice(8, 13) !== 'Array') {
        throw new Error('参数有误');
    }
    
    let result = context.fn(...args);
    delete context.fn
    return result
}

// 测试
var b = {
	value: 2
};
function getb(age) {
	console.log(age)
	console.log(this.value)
}
getb.myApply(b, [5,4]); //5 4, 2
getb.myApply(b, 3);   //抛出错误