call、apply及bind的实现原理

1. call和apply

callapply 的功能相同,都是改变 this 的指向,并立即执行函数。区别在于传参方式不同。
func.call(thisArg, arg1, arg2, ...):第一个参数是 this 指向的对象,其它参数依次传入。
func.apply(thisArg, [argsArray]):第一个参数是 this 指向的对象,第二个参数是数组或类数组。

2. call的实现原理

  • 思考过程

我们知道,函数都可以调用 call,说明 call 是函数原型上的方法,所有的实例都可以调用。即: Function.prototype.call
其次,如果第一个参数没有传入,在全局环境下,那么默认this指向 window(浏览器) / global(node)(非严格模式);
传入 call 的第一个参数是 this 指向的对象,根据隐式绑定的规则,我们知道 obj.foo()foo() 中的 this 指向 obj,因此我们可以这样调用函数 thisArgs.func(...args),所以相应的func中的this就指向了thisArgs,然后返回执行结果。

  • 原理实现
Function.prototype.ca_ll = function() {
    // 剩余运算符,得到的是一个数组,包含除了this值的其他参数
    let [thisArgs, ...args] = arguments;
    if(!thisArgs) {
        thisArgs = typeof window === 'undefined' ? global : window;
    }
    thisArgs.func = this;
    let result = thisArgs.func(...args);
    delete thisArgs.func;  // thisArgs上并没有func属性,所以执行结果之后需要移除
    return result;
}

// 测试用例
var foo = {
    name: 'zl'
}
function func(job, age) {
    console.log(this.name);
    console.log(job, age);
}

func.ca_ll(foo, 'coder', 45);  //zl coder 45

3. apply的实现原理

  • 思考过程

apply的实现过程和call的实现过程类似,只是对于参数的处理有些不同。

  • 原理实现
Function.prototype.app_ly = function() {
    let [thisArgs, args] = arguments;
    let result;  // 函数返回结果
    if(!thisArgs) {
        thisArgs = typeof window === 'undefined' ? global : window;
    }
    thisArgs.func = this;
    if(!args) {
        // 第二个参数为null或者是undefined
        result = thisArgs.func();
    } else {
        result = thisArgs.func(...args);
    }
    delete thisArgs.func;
    return result;
}

// 测试用例
let foo = {
    name: 'zl'
}

function func(job, age) {
    console.log(this.name);
    console.log(job, age);
}

func.app_ly(foo, ['coder', 45]);  //zl coder 45

4. bind的实现原理

bindcall/apply 有一个很重要的区别,一个函数被 call/apply 的时候,会直接调用,但是 bind 会创建一个新函数。当这个新函数被调用时,bind() 的第一个参数将作为它运行时的 this,之后的一序列参数将会在传递的实参前传入作为它的参数。

bind的实现见柯里化一篇https://blog.csdn.net/zl13015214442/article/details/89424840

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值