理解call和实现call

js里对call的定义:数组

调用一个对象的一个方法,以另外一个对象替换当前对象。call方法接受如下参数(obj,argument1,argument2,...)。bash

咱们用call写一个小demo:函数

如上图咱们就能够很直观的理解js对call的定义。调用window对象下的fn方法,用obj对象替换了window对象。可能这句话理解仍是有些歧义,咱们以后再解释。ui

为何说obj对象替换了window对象?见图:this

咱们从代码里看到直接调用fn输出window下的name。由于fnwindow对象下,kack也在window下。 当咱们用call的时候,把window对象替换成了obj,因此输出了obj的name:'tom'spa

对于call的实现分析:prototype

  1. call改变了this指向;
  2. 调用的方法执行了;
  3. call接受多个参数;

问题一:咱们如何改变一个方法的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方法!

相关文章
相关标签/搜索