一道阿里面试题,彻底明白call源码的原理
2020-07-12 17:19
423 查看
call的语法如下
语法:函数.call([context],[params1],....)
函数基于原型链找到Function.prototype.call这个方法,并且把它执行,在call方法执行的时候完成了一些功能
- 让当前函数执行
- 把函数中的THIS指向改为第一个传递给CALL的实参
- 把传递给CALL其余的实参,当做参数信息传递给当前函数
- 如果执行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
解释说明:
- fn1.call(fn2);
* 先找到Function原型上的call方法让其执行 * call执行的时候会让fn1执行,并且把fn1中的this改为了fn2,结果为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
- Function.prototype.call(fn1);
* 本质是让Function.prototype执行,所以并没有任何输出结果
- 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/)
相关文章推荐
- 彻底明白Redis主从同步原理
- 惭愧,今天看了jdk源码,才彻底明白为什么覆盖了equals()也要覆盖hashCode()
- 面试总被问到HTTP缓存机制及原理?看完你就彻底明白了
- 突然彻底明白了Stencil Shadow Volume的原理
- OpenJDK源码研究笔记(二)-Comparable和Comparator2个接口的作用和区别(一道经典的Java笔试面试题)
- 一道阿里多线程面试题分析
- 彻底明白Redis持久化原理
- 30分钟,让你彻底明白Promise原理
- 多角度让你彻底明白yield语法糖的用法和原理及在C#函数式编程中的作用
- Android热更新方案之阿里AndFix 原理以及源码解析
- HashMap的实现原理+阿里HasMap面试题
- 哈希、HashMap原理及源码、Hash的一些应用面试题
- 30分钟,让你彻底明白Promise原理
- Android热更新方案之阿里AndFix 原理以及源码解析
- java-多线程-一道阿里面试题分析
- 阿里面试官必问21 个刁钻的HashMap 面试题,这次让你彻底搞懂
- 阿里一道面试题——完全二叉树的最后一颗节点
- 一道“简单”的面试题_自动装箱和拆箱源码解析
- Java基础面试题2-HashMap的源码,实现原理,底层结构
- 一道传说中的阿里面试题