function fn1() { console.log(1); } function fn2() { console.log(2); } fn1.call(fn2); // 1 fn1.call.call(fn2); // 2
首先
fn1
通过原型链找到Function.prototype
上的call
方法,然后再让call
方法通过原型再找到Function
原型上的call
(因为call
本身的值也是一个函数,所以同样可以让Function.prototype
),在第二次找到call
的时候再让方法执行,方法中的this
是fn1.call
,而this被fn2替代,然后再让fn1.call
执行。Function.prototype.call = test; function test (context) { // 改变fn中的this关键字 // eval(....); // 让fn方法执行 this(); // 此时的this就是fn1 };
fn1.call.call(fn2)就是test.call(fn2);test.call(fn2)中的this就是test,然后把call中this改成fn2,然后执行
Function.prototype.call = test; function test (context) { // 改变fn中的this关键字 // eval(....); // 让fn方法执行 fn2(); //2 };
Function.prototype.myCall=function(myobj,...args){ if(typeof myobj==='Function'){ throw new TypeError('error') } const fn=symbol('fn') //唯一值 myobj=myobj || window //若没有传入对象,则绑定到window上 myobj[fn]=this //把函数赋值到对象的某个属性 const result=myobj[fn](...args) delete myobj[fn] //删除fn声明 return result }
结合mycall分析:
- 先将 fn2 赋给临时变量 myobj。
- this 所指向的对象就是一个函数对象:Function.prototype.myCall()。所以赋给 object.fn 临时属性指向的就是 Function.prototype.myCall()方法。
- 由于 arguments 长度为 1,所以直接执行 myobj.fn()方法,也就是 myobj.myCall(),也就是 fn2.myCall()。
- fn2.myCall()实际上执行的是 global.fn2(),具体执行过程就不再熬述了,故输出了 2,没有返回值。
对call,apply的看法,理解
首先需要了解apply,call的基本用法,其目的是改变调用方法中的this指向,将其指向为传入的对象
var console = window.console || {log: function () {}}; var log = console.log; console.log = function(tips,message){ Function.prototype.apply.call(log, console, arguments); //Function.prototype.call.call(log, console, arguments); //Function.prototype.call.apply(log, [console, arguments]); //传统方式 //var args=[].slice.call(arguments); //log.apply(console,args); }
分析:
该怎么理解Function.prototype.apply.call(log,console,arguments);呢
首先可以将Function.prototype.apply看成一个整体-->FunctionApply
FunctionApply.call(log,console,arguments);
那么将此句翻译一下
log.FunctionApply(console,arguments);
然后再翻译一下,你就懂了吧,就是一个普通方法调用了
console.log(arguments);
Function.prototype.call.apply(log,[console.arguments]);
FunctionCall.apply(log,[console,arguments]); log.FunctionCall(console,arguments); console.log(arguments);
tips:
Function.prototype.apply.call 等同于Function.prototype.call.call
Function.prototype.call.apply 等同于 Function.prototype.apply.apply
function testA(a){ console.log('aaaa',a); } Function.prototype.apply.call(testA,window,['Mike']) == testA.apply(window,['Mike']) == window.testA('Mike'); //Function.prototype.call.call(testA,window,['Mike']); //Function.prototype.apply.apply(testA,[window,['Mike']]); //Function.prototype.call.apply(testA,[window,['Mike']]);