区别
相同点:
- 都可以改变函数的this指向
- 第一个参数都是this要指向的对象,如果没有这个参数或参数为undefined或null,则默认指向全局window
- 都可以利用后续参数传参
不同点:
- call可以传入多个参数;apply需要传入一个参数对象(数组或类数组);bind可以分开传参,例如:const foo = fn.bind(this, 1, 2); foo(3, 4)
- call、apply会立即执行,bind不会立即执行,而是返回一个修改this后的函数
实现call
Function.prototype._call = function (thisArg, ...args) {
// this指向调用_call的函数
const fn = this
// 如果要绑定的对象为undefined或null,则默认指向全局对象
thisArg = thisArg !== undefined && thisArg !== null ? Object(thisArg) : window
// 利用this的隐式绑定规则,将函数的this绑定到指定对象上
thisArg.fn = fn
const res = thisArg.fn(...args)
// 删除新增的fn方法
delete thisArg.fn
return res
}
测试:
function foo(a, b) {
console.log(this.name, a, b)
}
const obj = { name: 'xiaoming' }
foo.call(obj, 20, 30) // xiaoming 20 30
foo._call(obj, 20, 30) // xiaoming 20 30
实现apply
apply和call差别不大,只是传入函数参数的形式不同
完整版:
Function.prototype._apply = function (thisArg, arrArg = []) {
const fn = this
thisArg = (thisArg !== undefined && thisArg != null) ? Object(thisArg) : window
thisArg.fn = fn
const res = thisArg.fn(...arrArg)
delete thisArg.fn
return res
}
简化版:
Function.prototype._apply = function (thisArg, arrArg = []) {
const fn = this;
return fn._call(thisArg, ...arrArg);
}
测试:
function foo(a, b) {
console.log(this.name, a, b)
}
const obj = { name: 'xiaohong' }
foo.apply(obj, [10, 20]) // xiaohong 10 20
foo._apply(obj, [10, 20]) // xiaohong 10 20
实现bind
完整版:
Function.prototype._bind = function (thisArg, ...args) {
const fn = this
thisArg = (thisArg !== null && thisArg !== undefined) ? Object(thisArg) : window
// 返回一个新函数作为绑定函数
return function (...otherArgs) {
thisArg.fn = fn
const res = thisArg.fn(...args, ...otherArgs)
delete thisArg.fn
return res
}
}
简化版:
Function.prototype._bind = function (thisArg, ...args) {
const fn = this;
return function (...otherArgs) {
return fn._apply(thisArg, args.concat(otherArgs));
};
};
测试:
function foo(a, b) {
console.log(this.name, a, b)
}
const obj = { name: 'xiaoli' }
const res = foo.bind(obj, 30)
const res1 = foo._bind(obj, 30)
res(40) // xiaoli 30 40
res1(40) // xiaoli 30 40
标签:面试题,const,call,thisArg,apply,foo,fn
From: https://www.cnblogs.com/ccboom/p/18073703