手写Js函数-call & apply

一、call & apply

我们先举个栗子看下call和apply的作用:

	//全局变量name
	name='window\'s name'
	let obj = {
	  name:'XDD'
	}
	function fun(a,b){
	  console.log(this.name)
	  console.log(a+b)
	}
	fun(1,2)     			//此时this是window,output: window's name  	3
	fun.call(obj,1,2)		//此时this是obj,   output: XDD				3
	fun.apply(obj,[1,2])	//此时this是obj,   output: XDD				3

可以看出来,这两者的作用是改变调用者的this指向,要注意的是它们的第二个参数的形式不同。

call()的第二个参数的形式需为 参数列表

apply()的第二个参数的形式需为 数组

二、找找思路

既然知道了他两的作用,那么问题也很明了了:如何改变调用者的this指向,让其重新指向我们传入的对象?
在思考这个问题之前,咱不妨先思考一下在上面的栗子中,如果不使用call和apply函数,我们该怎么在函数fun执行时把它的this指向obj?相信很多小伙伴都能想到下面这种简单有效的方法——把fun变为obj对象的方法,这样fun执行时,this就指向了obj。如下所示:

	let obj = {
	  name:'XDD',
	  fun: function(a,b){
	    console.log(this.name)
	    console.log(a+b)
	  }
	}
	obj.fun(1,2)  //output: XDD   3

所以,我们可以按照这种思路来实现我们的call函数和apply函数。

三、照葫芦画瓢

call的实现过程

	
	Function.prototype.newCall = function(option,...args){
		//如果传入的对象为null||undefined,我们就将option变成window
	  	option = typeof option === 'object'?option:window;
	  	
		//防止覆盖原有的属性,创建一个独一无二的值 —— fn。   Symbol(1)是不等于Symbol(1)的
	  	const fn = Symbol()
	  	//此时的this就是newCall的调用者,我们将其变成option对象的一个方法,
	  	option[fn] = this
	  	
	  	//执行该方法,并将传入的(...args)作为他的参数,将执行的结果保存在变量result中
	  	let result = option[fn](...args)
	  	//从option对象里删除掉这个方法(有“工具人”内味儿了)
	  	delete option[fn]
	  	return result;
	}

apply的实现过程

	Function.prototype.newapply = function(option,args){
	  	option = typeof option === 'object'?option:window;
	  	const fn = Symbol()
	  	option[fn] = this
	  	let result;
	  	result = option[fn](...args)
	  	delete option[fn]
	  	return result;
	}

call和apply函数就都完成了。这时候,可能有些小伙伴会问,明明这apply和call的代码没啥区别,为什么还要再复制粘贴一遍?难道你是老CV了?o_O??
如果你有此疑问,请先回想下第一点中提到的call和apply的区别,再看看这两个函数的第二个参数(别问我咋知道有人这么想的T_T,自己细品噢……)

四、与bind区别

call 和 apply 还有 bind都有改变调用者的this指向的能力,但是call、apply 两者和bind的区别在于,bind函数返回的是一个函数,而call和apply返回的是执行结果。本来bind函数应该放在这里一起写的,但是因为先前已经写过了,所以在这里奉上链接手写实现bind函数,有兴趣的小伙子可以去see see。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值