call/apply/bind区别、用法和实现

36 阅读1分钟

call()、apply()、bind()都能改变函数this的指向

call()、apply()调用以后立即执行,bind()调用后返回一个新的函数

call()和bind()能传参数或者数组,apply只能传数组

call()

function test(a, b) {
	console.log(a, b, this.name);
}
let obj = {
	name: '张三'
};
test.call(obj, '李四', '王五')
function test(a, b) {
	console.log(a, b, this.name);
}
let obj = {
	name: '张三'
};
test.call(obj, ['李四', '王五'])

实现

简单讲就是给对象新增一个方法,然后调用该对象的方法

Function.prototype.myCall = function(obj, ...args) {
	let target = obj || window;
	let key = Symbol();
	target[key] = this;
	let res = target[key](...args);
	delete target[key];
	return res;
}
function test(a, b) {
	console.log(a, b, this.name);

}
let obj = {
	name: '张三'
};
test.myCall(obj, ['李四', '王五']);

apply()

function test(a, b) {
	console.log(a, b, this.name);
}
let obj = {
	name: '张三'
};
test.apply(obj, ['李四', '王五'])

实现

和call区别是入参变成了数组

Function.prototype.myApply = function(obj, args) {
	let target = obj || window;
	let key = Symbol();
	target[key] = this;
	let res = target[key](...args);
	delete target[key];
	return res;
}
function test(a, b) {
	console.log(a, b, this.name);

}
let obj = {
	name: '张三'
};

test.myApply(obj, ['李四', '王五']);

bind()

function test(a, b) {
	console.log(a, b, this.name);
}
let obj = {
	name: '张三'
};
test.bind(obj, '李四', '王五')();
function test(a, b) {
	console.log(a, b, this.name);
}
let obj = {
	name: '张三'
};
test.bind(obj, ['李四', '王五'])()

实现

把新增函数方法和调用的步骤封装到函数返回了,这里用到了闭包

Function.prototype.myBind = function(obj, ...args) {
	let target = obj || window;
	const key = Symbol();
	return (...innerArgs) = >{
		target[key] = this;
		let res = target[key](...args, ...innerArgs) delete target[key];
		return res;
	}
}
function test(a, b, c) {
	console.log(a, b, c, this.name)
}
let obj = {
	name: '张三'
}
let fun = test.myBind(obj, '李四');
fun('王五', '麻六');
fun('王五五', '麻六六');

juejin.cn/post/712823…