js学习笔记:记录一次apply和call方法的使用

之前做项目的时候,有个bug需要在ie8调试,所以加了console.log,但是这个方法好像在ie8上用不了,后来在网上找了个封装了console对象的代码,用于调试,这个代码应该是从源码抄过来的,值得研究下,代码如下:

window._console = window.console;//将原始console对象缓存
window.console = (function (orgConsole) {
   return {//构造的新console对象
      log: getConsoleFn("log"),
      debug: getConsoleFn("debug"),
      info: getConsoleFn("info"),
      warn: getConsoleFn("warn"),
      exception: getConsoleFn("exception"),
      assert: getConsoleFn("assert"),
      dir: getConsoleFn("dir"),
      dirxml: getConsoleFn("dirxml"),
      trace: getConsoleFn("trace"),
      group: getConsoleFn("group"),
      groupCollapsed: getConsoleFn("groupCollapsed"),
      groupEnd: getConsoleFn("groupEnd"),
      profile: getConsoleFn("profile"),
      profileEnd: getConsoleFn("profileEnd"),
      count: getConsoleFn("count"),
      clear: getConsoleFn("clear"),
      time: getConsoleFn("time"),
      timeEnd: getConsoleFn("timeEnd"),
      timeStamp: getConsoleFn("timeStamp"),
      table: getConsoleFn("table"),
      error: getConsoleFn("error"),
      memory: getConsoleFn("memory"),
      markTimeline: getConsoleFn("markTimeline"),
      timeline: getConsoleFn("timeline"),
      timelineEnd: getConsoleFn("timelineEnd")
   };
   function getConsoleFn(name) {
      return function actionConsole() {
         if (typeof (orgConsole) !== "object") return;
         if (typeof (orgConsole[name]) !== "function") return;//判断原始console对象中是否含有此方法,若没有则直接返回
         return orgConsole[name].apply(orgConsole, Array.prototype.slice.call(arguments));//调用原始函数
      };
   }
}(window._console));

 

这里面比较有意思的是getConsoleFn方法,这个方法通过apply和call方法,调用了console对象的原始函数,下面分析这个方法里用到的其他方法。

首先引入三个方法的介绍:

1、slice方法:英文意为截取,类似subString,具体用法很简单,这里不做介绍,如果忘了的同学可百度。

这个方法有两个,一个是String对象的slice,截取字符串用的,第二个是Array对象的slice方法,截取数组用的。这两个方法的作用是一样,只是作用的对象不一样,所以分别定义在两个对象下面;

2、call方法,总结地来说,这个方法的作用是转换this引用的对象。

具体的介绍是:调用一个对象的一个方法,用另一个对象替换当前对象。例如:B.functionX.call(A,args1,args2...);即A对象调用B对象的方法functionX。

这里做了一个this引用的转换,把functionX原先的this对象B转换成了A,所以等价于((B)A).functionX(args1,args2...)。其中call方法还多做了一件事,把A对象转化成B对象, 因为functionX是B对象里的,A对象里不一定有该方法。args1,args2代表多个参数列表,类似于java里的String...

3、apply方法,和call方法作用一致,而不同之处在于传递的参数,apply最多只能有两个参数——新this对象和一个数组argArray,如果arg不是数组则会报错TypeError

 

下面开始分析getConsoleFn方法做了什么事:

return orgConsole[name].apply(orgConsole, Array.prototype.slice.call(arguments));//调用原始函数

抛开方法第1、2行不痛不痒的判断,直接看上面这行代码,orgConsole[name]是console对象的某个方法,例如:console.log。arguments是调此方法的入参,例如:console.log("123")。

那么这行代码可以理解为:

return console.log.apply(orgConsole, Array.prototype.slice.call("123"));//调用原始函数

 

这个代码的第一步是执行Array.prototype.slice.call("123"),等价于:toArray ("123").slice()。此处将字符串"123"转Array的过程如下:

var toArray = function(s){
    var args = []; 
    for (var i = 1; i < s.length; i++) { //必须带有length属性才能转Array,字符串带length属性,所以能转
        args.push(s[i]);
    }
}

 

slice方法没有参数,所以返回了Array对象本身,我感觉slice方法啥事没干,相当于是个工具人,只是为了配合call方法把参数转成Array。

经过上面的分析,此时这行代码可以理解为:

return console.log.apply(orgConsole, toArray("123"));//调用原始函数

 

最后把apply方法转换成:

return orgConsole.log(toArray("123"));//调用原始函数

 

回到最初的代码,可以看到orgConsole变量值为window.console,所以getConsoleFn最终形态为:

return window.console.log(toArray("123"));//调用原始函数

 

这样是不是就很容易理解了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值