call
call()
方法使用一个指定的 this
值和单独给出的一个或多个参数来调用一个函数。
语法:function.call(thisArg, arg1, arg2, ...)
注意:该方法的语法和作用与 apply()
方法类似,只有一个区别,就是 call()
方法接受的是一个参数列表,而 apply()
方法接受的是一个包含多个参数的数组。
// 核心思想
// 将fn做为对象的一个属性,然后对象打点调用函数,这样函数中的this就会指向对象
// 注意点:
// 1.原生的call函数,如果处于非严格模式下,则指定为 null 或 undefined 时会自动替换为指向全局对象,原始值会被包装。
// 2. globalThis 是 ES10 的语法,如果在node环境下,则指向global,如果在浏览器环境下则指向windows
function call(fn, obj, ...args) {
if (obj == undefined || typeof obj !== 'object') {
obj = globalThis;
}
// 将fn做为obj的属性
obj.temp = fn;
// 展开剩余参数
const result = obj.temp(...args);
delete obj.temp;
// 一定要记得将函数的执行结果进行返回 虽然可能函数并没有返回值
return result;
}
测试
let testObj = { c: 5 };
global.c =7
function add(a, b) {
console.log(a+b+this.c);
}
call(add,null,2,4) //13
call(add,testObj,2,4) //11
apply
apply()
方法调用一个具有给定this
值的函数,以及以一个数组(或类数组对象)的形式提供的参数。
从 ECMAScript 第5版开始,可以使用任何种类的类数组对象,就是说只要有一个 length
属性和(0..length-1)
范围的整数属性。例如现在可以使用 NodeList
或一个自己定义的类似 {'length': 2, '0': 'eat', '1': 'bananas'}
形式的对象。
function apply(fn,obj,arr) {
if (obj == null || typeof obj !== 'object') {
obj = globalThis;
}
obj.temp = fn;
// 注意这里还是需要用到展开运算符
// 尽管给apply传的是一个数组,但实际函数运行中还是单个的参数
let result = obj.temp(...arr);
delete obj.temp;
return result;
}
测试
function add(a, b) {
return a + b + this.c;
}
let obj = { c: 5 };
console.log(apply(add, obj, [1, 2])); // 8
console.log(add.apply(obj,[1,2])); //8
bind
bind()
方法创建一个新的函数,在 bind()
被调用时,这个新函数的 this
被指定为 bind()
的第一个参数,而其余参数将作为新函数的参数,供调用时使用。
我觉得是最复杂的一个!
function call(fn, obj, ...arg) {
if (obj == null) {
obj = globalThis;
}
obj.temp = fn;
let result = obj.temp(...arg);
delete obj.temp;
return result;
}
function bind(fn, obj, ...arg) {
// 会返回一个函数,返回的函数被调用的时候还是可以接收参数
return function (...arg1) {
// 执行call
return call(fn,obj,...arg,...arg1)
}
}
测试
function add(a, b) {
return a + b + this.c;
}
let obj = {
c: 11
}
// 原生bind
// 可见bind由下面两种传参方式
let fn = add.bind(obj, 1, 2);
console.log(fn()); //14
let fn1 = add.bind(obj);
console.log(fn1(1,2)); //14
//自己写的bind
let fn2 = bind(add, obj, 1, 2);
console.log(fn2()); //14
let fn3 = bind(add, obj);
console.log(fn3(1,2)); //14