Ⅰ、call 函数的简介:
1、call 函数的用法:
fn.call(obj,1,2);
A、call() 函数中的第一个参数表示:想让 this 指向的对象 (obj);
B、call() 函数中的第二及以后参数表示:传进去的实参;
2、call 函数的功能:
其一、让函数立执行;
其二、可改变 this 的指向;
其三、可实现继承问题;
Ⅱ、call 函数如何调用:
1、call() 函数的调用过程:
var obj = { a: 1 };
function fn(x, y) { // 每个函数都会有 call 方法;
console.log(this);
return x + y;
}
console.log(fn.call(null, 1, 2));
// 此时的输出结果为:Window, 3;
// 若此时的 call() 函数中的第一个参数未传值,或传值为 null 时,此时的 fn 中的 this 指向为:Window;
console.log(fn.call(obj, 1, 2));
// 此时的输出结果为:{a: 1}, 3;
// 若此时的 call() 函数中的第一个参数非空而是 obj ,那么此时的 fn 中的 this 指向为:obj;
2、call() 函数的调用结果展示为:
Ⅲ、模拟 call 函数的实现原理;
1、对 call 函数原理的模拟 (即:实现自己的 myCall 方法) ;
Function.prototype.myCall = function (context) {
// 其中 context 参数是指:改变 this 指向,而待指向的的参数值(如:obj);
// 此时是在 Function 的原型链上来添加 myCall() 函数, 那么此时该函数中的 this 指向的是:调用该 myCall() 方法的实例或函数;
// 处理参数(即:实参);
var args = [...arguments].slice(1);
// 将 arguments 的值从第二个截取后,放到 args 的数组里;
// 该操作是将传入的实参值转化成数组,以待后面使用;
context = context || window;
// 当传的值为 null 或没传值时(均为:false),此时 context 的值为:Window;
// 当传值时(为:true),此时的 context 的值为:context;
context.fn = this;
// 此时 this 指向的是:将来调用 myCall 方法的那个函数;
// 而又由于 context 调用 fn 这个属性是指向 this, 因此此时的 this 就指向了 context; 那么此时就完成了 this 指向 context 的目的;
// 该操作是:让将来调用 myCall 方法的那个函数,封装到 context 的一个属性中去(即:context.fn);
// 那么此时的 context.fn 就代表的是调用 myCall 方法的那个函数,它是一个函数;
var r = context.fn(...args);
// 该操作是:调用 context.fn() 函数,也就是调用了 '调用 myCall' 的函数;
// 并传参为:'...args', 也就是将 args 数组中的值展开作为参数传入函数中;
// 此时也就完成了,将 this 的指向为:context; 且还运行了 '调用 myCall' 的函数,并将参数传进去; (即:已经实现了 call() 函数的功能);
return r;
// 然后再将操作后的值返回;
}
var obj = { a: 1 };
function fn(x, y) {
console.log(this);
return x + y;
}
var sum = fn.myCall(obj, 1, 2);
console.log(sum);
// 此时的输出结果为:'{a: 1, fn: ƒ}', 3;
// 输出结果都正确,只是 context 中添加一个 fn 属性,但添加一个属性也是没大影响的;
// 注意:此时并没有模拟 this 指向 Window 的情况;
2、模拟的 myCall() 函数的调用结果展示为:
Ⅳ、小结:
其一、哪里有不对或不合适的地方,还请大佬们多多指点和交流!
其二、如果关于 call 、apply、bind 用法和实现原理不详细,请参考如下地址文章:https://blog.csdn.net/weixin_43405300/article/details/121894586?spm=1001.2014.3001.5501