call的实现
先看call的用法
1  | var obj = {  | 
我们知道,这里show方法执行了,同时将this指向了obj这个对象。现在要模拟这个实现。
主要过程是转变为类似以下的形式
1  | var obj = {  | 
以上面的例子为例,就是要在obj对象里添加一个方法,这个方法就是我们外层要执行的方法,然后调用这个方法。我们自己添加了一个方法,最后执行完肯定要删掉它,保持原来的对象不变。
1  | Function.prorotype.myCall = (context) => {  | 
我们知道call是可以接收其他参数的。对于接收不定数量的参数,我们自然想到用arguments。
call接收的第一个参数是指定的对象,剩下的参数我们就从arguments[1]开始取啦。
1  | var args = [];  | 
剩下的步骤就是把args展开放大obj.fn里了
1  | eval('context.fn(' + args + ')')  | 
这里需要了解一下eval。eval是将接收的字符串以js代码的方式执行,同时,这个例子里的args会调用Array.toString()方法。看一下Array.toString方法
1  | var arr = [1, 2, 3];  | 
所以 eval('context.fn(' + args +')') 这段代码,最后实际是变为类似下面这种
1  | context.fn(arguments[1], arguments[2], ........)  | 
还有需要注意的点
- 指定对象的参数可能为null
 - 函数可能会有返回值
 
1  | Function.prototype.myCall = function(context) {  | 
apply的实现
跟call几乎一样,apply因为接受的第二个参数是固定的数组类型的参数
1  | Function.prototype.apply = function(context, arr) {  |