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) { |