实现 call、apply 和 bind 方法

call、apply 和 bind本质上都是要改变 this 的指向,在实现过程中一定要时刻搞清楚 this 的指向
首先考虑一下这个场景

function show() {
	console.log(this.name);  // undefined
}

const person = {
	name: 'white_give'
};

如果不用callapplybind,如何让 show 方法里的 this 指向 person 对象呢?
可以像下面这样做

const person = {
	name: 'white_give',
    show: function () {
    	console.log(this.name);
    }
};

其实我们手写实现 call 、 applybind 时也是这个思路

call

call 的第一个参数为普通函数,其余参数则为该函数的参数

Function.prototype.myCall = function (ctx, ...args) {
	/**
     * this 指向 myCall 函数的调用者
     * ctx 为 this 要指向的对象
     */
    ctx = ctx || window
	ctx.fn = this; // 相当于给 person 对象增加了一个 fn 属性,属性值是 show 函数
    const result = ctx.fn(...args);
    delete ctx.fn;
    return result;
}

apply

apply的第一个参数是普通函数,第二个则为该函数的参数祖成的数组

Function.prototype.myApply = function (ctx, args) {
	/**
     * this 指向 myCall 函数的调用者
     * ctx 为 this 要指向的对象
     */
    ctx = ctx || window
	ctx.fn = this; // 相当于给 person 对象增加了一个 fn 属性,属性值是 show 函数
    const result = args.length > 0? ctx.fn(...args) : ctx.fn();
    delete ctx.fn;
    return result;
}

bind

bindcall差不多,最大的区别是他返回的是一个函数,需要再次调用才生效

Function.prototype.myBind = function (ctx) {
	const args = Array.prototype.slice.call(arguments, 1);
	const self= this
	const fun= function () {};
	const fn = function () {
		const total = args.concat(...arguments)
		if(this instanceof self) {
			self.apply(this, total )
		} else {
			self.apply(ctx, total )
		}
    }

	const fn=  function() {
		let total = arg.concat(arguments)
		// 如果使用 new 关键字,这里的 this 指向的是 newFn 对象
        if (this instanceof fn) {
        	// 将 myBind 调用者的 this 改为 newFn 对象
        	that.apply(this, args);
        } else {
        	that.apply(ctx, args);
        }
     }
     
    fun.prototype = this.prototype;
    fn.prototype = new fun();

    return fn;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值