前端面试题javascript篇——call-apply-bind

call-apply-bind三者的作用,区别以及内部实现

1. call-apply-bind三者的作用

在JavaScript中,call-apply-bind是Function对象自带的三种方法,它们的作用都是用来改变函数内的this指向,传递的第一个参数都是this所要指向的对象,而且它们三个都可以传递参数(后续传值)。

2. call-apply-bind三者的区别

  • call:调用一个对象的一个方法,用另一个对象替换当前对象,在传递参数的时候需要一个一个进行传递,而且定义完立即执行,返回值为调用方法的返回值,如果调用的方法没有返回值,则返回undefined
obj.call(obj1,arg1,arg2,arg3....);
  • apply:和call很类似,都是立即执行,返回值为调用方法的返回值,如果调用方法没有返回值,则返回undefined,唯一不同的是,apply在传递参数的时候需要以数组的形式
obj.apply(obj1,[arg1,arg2,arg3.....]);
  • bind:除了返回值是函数以外,它在传递参数的时候和call一样,都是一个一个传递,它在调用之后返回一个新的函数,不会立即执行
obj.bind(obj1,arg1,arg2,arg3...)();

3. call-apply-bind三者的内部实现

在内部实现的时候,需要把函数绑定在Function原型上,是原型上面的方法

  • call
Function.prototype.myCall = function(context = window, ...args) {
	if (this === Function.prototype) {
		return undefined;   //判断当前this是否为函数,用于防止Function.prototype.myCall()直接调用
	}
	context = context || window;   //context为可选参数,如果不传的话,默认指向window
	const fn = Symbol();    //利用symbol进行定义,可以保证不会重名
	context[fn] = this;    //将当前函数赋给这个属性,这样之后执行context[fn]的时候,fn里面的this指向就为context了
	const result = context[fn](...args);
	delete context[fn];  //调用完后立即删除symbol属性
	return result;
}

//调用
let person1 = {
	name:'王',
	age:18,
	say(...args){
		console.log(`名字为${this.name},年龄为${this.age},参数为${args}`);
	}
}
let person2 = {
	name:'李',
	age:20
}
person1.say.myCall(person2,1,2,3);

//输出  名字为李,年龄为20,参数为1,2,3
  • apply
Function.prototype.myApply = function(context = window,args){
	if(this === Function.prototype){
		return undefined;
	}
	context = context || window;
	const fn = Symbol();
	context[fn] = this;
	let result;
	if(Array.isArray(args)){
		result = context[fn](...args);
	}else{
		result = context[fn]();
	}
	delete context[fn];
	return result;
}

//调用
let person1 = {
	name:'王',
	age:18,
	say(...args){
		console.log(`名字为${this.name},年龄为${this.age},参数为${args}`);
	}
}
let person2 = {
	name:'李',
	age:20
}
person1.say.myApply(person2,[1,2,3]);

//输出  名字为李,年龄为20,参数为1,2,3
  • bind
Function.prototype.myBind = function(obj,...args){
	let self = this;
	return function(){
		let newArgs = args.concat(...arguments);
		self.call(obj,newArgs);
	}
}

//调用
let person1 = {
	name:'王',
	age:18,
	say(...args){
		console.log(`名字为${this.name},年龄为${this.age},参数为${args}`);
	}
}
let person2 = {
	name:'李',
	age:20
}
person1.say.myBind(person2,1,2,3)(4,5);

//输出  名字为李,年龄为20,参数为1,2,3,4,5
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值