js里对call的定义:数组
调用一个对象的一个方法,以另外一个对象替换当前对象。call方法接受如下参数(obj,argument1,argument2,...)。bash
咱们用call写一个小demo:函数
如上图咱们就能够很直观的理解js对call的定义。调用window对象下的fn方法,用obj对象替换了window对象。可能这句话理解仍是有些歧义,咱们以后再解释。ui
为何说obj对象替换了window对象?见图:this
咱们从代码里看到直接调用fn
输出window
下的name
。由于fn
在window
对象下,kack
也在window
下。 当咱们用call
的时候,把window
对象替换成了obj
,因此输出了obj的name:'tom'
。spa
对于call的实现分析:prototype
问题一:咱们如何改变一个方法的this的指向呢? 问题二:如何去改变this指向,有去调用这个方法? 问题三:如何接受多个参数?再去执行? code
能够看到咱们给一个对象添加一个fn1属性,并把fn方法赋给这个属性,就至关于改变了fn里的this指向!而后再调用obj.fn1这个属性,不就执行了fn方法吗?是否是很简单~ 那多出来的fn1属性怎么办?也很简单,把这个对象的属性删除不就能够么。。。那多个参数怎么办?咱们获取一个方法的参数能够经过arguments来获取,arguments是一个伪数组对象。而后遍历这个对象把属性再放到一个数组里,这样就能够取出来了。 最后一个问题:获得参数数组后怎么放到方法里去执行呢?咱们要用到eval()
函数,eval()
函数可计算某个字符串,并执行其中的的 JavaScript 代码。cdn
咱们先按上面的分析实现call:对象
Function.prototype._call = function(){
var args = [];
var obj = arguments[0] || window; // call 若是第一个参数传null,则这个对象是window
for(var i=1, len = arguments.length; i < len; i++){
// 由于执行一个函数传参通常都是传string类型,因此此处须要用字符串拼接,以后用eval去解析这个字符串。
args.push('arguments['+ i +']''); } obj.fn = this; // this就是调用_call的函数 // args = ['arguments[1]', 'arguments[2]', 'arguments[3]', ...]; // 此处执行eval时,会先调用args.toString(),而后执行eval时会从对应的arguments对象中取参数。 eval('obj.fn(' + args +')'); delete obj.fn; }; 复制代码
运行以上代码:
大功告成,能够看出咱们实现了call方法!