前端手撕代码——手撕call、apply、bind

文章详细解释了JavaScript中call、apply和bind的方法原理,通过自定义实现来展示它们如何改变函数调用的上下文以及参数传递的方式。call和apply主要区别在于参数传递形式,bind则是创建一个新的函数并保持上下文不变。
摘要由CSDN通过智能技术生成

call
实现原理:
把方法绑定到目标对象上,然后执行,执行完毕后在目标对象上删除

// call的实现原理是把方法绑定到目标对象上,借过来用,用完之后然后删除

Function.prototype._call = function(target, ...args){
    // 判断调用对象是不是函数
    if(typeof this !== "function"){
        throw new TypeError('error');
    }
    target = target || window;
    const key = Symbol('fn');
    target[key] = this;
    const res = target[key](...args);
    delete target[key];
    return res;
}

const B = {
    name: 'B',
    say(prefix, age) {
      console.log(`${prefix},my name is ${this.name},i am ${age} year old`)
    }
}
  
const A = {
    name:'小A'
}
  
B.say._call(A,'hello',3) // 'hello,my name is A,i am 3 year old'

apply
apply原理和call一样,区别在于传参方式不同,call是一个一个参数传递(obj, arg1, arg2…),而apply是将参数放在数组中传递(obj, [arg1, arg2…])

Function.prototype._apply = function(target, args){
    // 判断调用对象是不是函数
    if(typeof this !== "function"){
        throw new TypeError('error');
    }
    target = target || window;
    const key = Symbol('fn');
    target[key] = this;
    const res = target[key](...args);
    delete target[key];
    return res;
}

const B = {
    name: 'B',
    say(prefix, age) {
      console.log(`${prefix},my name is ${this.name},i am ${age} year old`)
    }
}
  
const A = {
    name:'小A'
}
  
B.say._apply(A,'hello', 3) // 'hello,my name is A,i am 3 year old'

bind函数
bind函数和call函数传参方式一样,但是bind函数并不会直接执行,而是将函数返回过来

// 自定义简陋版bind方法实现
Function.prototype._bind = function(context, ...args) {
    // 判断调用对象是不是函数
    if(typeof this !== "function"){
        throw new TypeError('error');
    }
    // 如果没有传入上下文对象,则默认为全局对象window
    context = context || window
    // 保存原始函数的引用,this就是要绑定的函数
    const _this = this
    // 返回一个新的函数作为绑定函数
    return function fn(...innerArgs) {
        // 判断返回出去的函数有没有被new,如果是new出来的,不给this作用域
        if(this instanceof fn){
            return new _this(...args, ...innerArgs);
        }
        // 使用 apply 方法将原函数绑定到指定的上下文对象上
        return _this.apply(context, [...args, ...innerArgs]);
    };
};

function foo(x, y, z) {
    this.name = "张三";
    console.log(this.num, x + y + z);
    console.log(this.name);
}
var obj = {
   num: 666
}
var foo2 = foo._bind(obj, 1,2,3);
console.log(new foo2);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值