您的位置:首页 > 职场人生

一道阿里面试题,彻底明白call源码的原理

2020-07-12 17:19 423 查看

call的语法如下

语法:函数.call([context],[params1],....)

函数基于原型链找到Function.prototype.call这个方法,并且把它执行,在call方法执行的时候完成了一些功能

  1. 让当前函数执行
  2. 把函数中的THIS指向改为第一个传递给CALL的实参
  3. 把传递给CALL其余的实参,当做参数信息传递给当前函数
  4. 如果执行CALL一个实参都没有传递,非严格模式下是让函数中的THIS指向WINDOW,严格模式下指向的是UNDEFINED

一个简单的铺垫

window.name = 'window';
let obj = {
name: 'hello'
};
function fn() {
console.log(this.name);
}
fn(); //window
// obj.fn(); //报错
obj.fn = fn;
obj.fn(); //'hello'

说明:当执行obj.fn = fn后,相当于执行全局下的fn,此时fn方法中的this变为了obj,call方法正是利用了这一点来实现的。

内置call的实现原理

window.name = 'window';
let obj = {
name: 'hello'
};

function fn(n, m) {
console.log(this.name); //hello
console.log(n + m); //30
}
Function.prototype.call = function call(context, ...arg) {
// this:fn 【重点】
context = context || window;
context.this = this;
context.this(...arg);
delete context.this; //把临时添加在obj上的fn属性删除
}

fn.call(obj, 10, 20);
// console.log(obj);//{name: "hello"}

一道经典的面试题

function fn1() {
console.log(1);
}

function fn2() {
console.log(2);
}
fn1.call(fn2); //1
fn1.call.call(fn2);//2
Function.prototype.call(fn1); //没输出
Function.prototype.call.call(fn1); //1

解释说明:

  1. fn1.call(fn2);
*	先找到Function原型上的call方法让其执行
*	call执行的时候会让fn1执行,并且把fn1中的this改为了fn2,结果为1.
  1. fn1.call.call(fn2);
第一次执行call方法:fn1.call.call(fn2)
*      context:fn2
*      this: fn1.call
*
*      fn2.(fn1.call) = fn1.call;
*      让fn2.(fn1.call)执行,相当于让fn1.call执行,此时fn1.call中的this变为fn2
*      即第一次执行call后的结果:fn1.call() -->this:fn2

* 第二次执行call方法:fn1.call()
*      context:undefined || window; -->所以context = window
*      this: fn2
*
*      window.fn2 = fn2;
*      window.fn2() -->等价于fn2(),this:window -->结果:输出2
  1. Function.prototype.call(fn1);
*	本质是让Function.prototype执行,所以并没有任何输出结果
  1. Function.prototype.call.call(fn1);
本质:让Function.prototype.call()执行,方法中的this:fn1
*      context:window
*      this: fn1
*
*      window.fn1 = fn1;
*      让window.fn1执行,相当于让fn1执行,此时fn1中的this变为window -->结果:输出1

小技巧:一个call了是让左边的函数执行,多个call是让传参的函数执行(this是window/undefined)

注:文章灵感来源于“珠峰培训”教学课程(http://www.zhufengpeixun.cn/)

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: