案例复现

var obj = {
plus: function(arg0, arg1) { return arg0 + arg1; }
}; function callMethod(context, method, arg0, arg1) {
var shift = [].shift;
shift.call(arguments);
shift.call(arguments); // Cannot call method 'apply' of undefined
return context[method].apply(context, arguments);
}
var result = callMethod(obj, 'plus', 17, 2);

该函数出错的原因是arguments对象并不是函数参数的副本。要注意的是,所有命名参数都是arguments对象中对应索引的别名。因此,即使通过shift方法移除arguments对象中的元素之后,context仍然是arguments[0]的别名,method仍然是arguments[1]的别名。这意味着,我们想提取的是context['plus'],但结果是17[2]。此时一切开始失控了!

代码注释版

function callMethod(context, method, arg0, arg1) {
var shift = [].shift;
shift.call(arguments);
shift.call(arguments); // 此时的arguments: [1, 2]
// context是arguments[0]的别名,值为1
// 同理method的值为2 // Cannot call method 'apply' of undefined
return context[method].apply(context, arguments);
}

解决方案

我们可以通过复制arguments对象修复callMethod函数的实现。

// 解决方案
function callMethod(context, method, arg0, arg1) {
var args = [].slice.call(arguments, 2);
return context[method].apply(context, args);
}

总结

  • 永远不要修改arguments对象
  • 使用[].slice.call(arguments)将arguments对象复制到一个真正的数组中再进行修改

参考:编写高质量JavaScript代码的68个有效方法

永远不要修改arguments对象的更多相关文章

  1. [Effective JavaScript 笔记]第23条:永远不要修改arguments对象

    arguments对象并不是标准的Array类型的实例.arguments对象不能直接调用Array方法. arguments对象的救星call方法 使得arguments可以品尝到数组方法的美味,知 ...

  2. 你不知道的JavaScript--Item11 arguments对象

    1.什么是arguments arguments 是是JavaScript里的一个内置对象,它很古怪,也经常被人所忽视,但实际上是很重要的.所有主要的js函数库都利用了arguments对象.所以ag ...

  3. 关于 js中的arguments 对象

    arguments对象包含了函数运行时的所有参数,arguments[0]就是第一个参数,arguments[1]就是第二个参数,以此类推.这个对象只有在函数体内部,才可以使用. var f = fu ...

  4. 在js中arguments对象的理解

    一.在函数调用的时候,浏览器每次都会传递进两个隐式参数 函数的上下文对象this 封装实参的对象arguments 二.arguments 对象 arguments 对象实际上是所在函数的一个内置类数 ...

  5. 使用 arguments 对象

    arguments 对象表示参数集合,它是一个伪类数组,拥有与数组相似的结构,可以通过数组下标的形式访问函数实参值,但是没有基础 Array 的原型方法. //函数没有定义形参,但是在函数体内通过 a ...

  6. arguments 对象的老历史

    引题:为什么 JavaScript 中的 arguments 对象不是数组 http://www.zhihu.com/question/50803453 JavaScript 1.0 1995 年, ...

  7. arguments 对象

    在函数体内,标识符arguments是指向实参对象的引用,实参对象是一个类数组对象 arguments[0],arguments.length arguments是什么? 答:1:arguments是 ...

  8. ES6教程-字符串,函数的参数,了解函数的arguments对象,js面向对象,设计模式-单例模式,解构赋值

    前言 主要讲解了ES6对字符串的拓展,包括includes,startsWith和endsWith,另外增加了字符串模板. Start includes()是否包含 startsWith()以什么开头 ...

  9. JavaScript arguments对象详解

    1. 什么是 arguments MDN 上解释: arguments 是一个类数组对象.代表传给一个function的参数列表. 我们先用一个例子直观了解下 JavaScript 中的 argume ...

随机推荐

  1. eclipse插件汇总

    subclipse http://subclipse.tigris.org/servlets/ProjectProcess?pageID=p4wYuA 话说eclipse组织也出了一个svn的插件,但 ...

  2. Java编译器如何生成重载和覆盖方法代码

    下面是一个很简单的例子,关于Java中的多态:方法重载和方法覆盖: 多态指的是方法在不同的时刻表现出不同的形式:在编译期间,这被叫做方法重载:方法重载允许相关的方法被同一个方法名字调用,这有时候被叫做 ...

  3. 天书笔记:HTML+CSS实现顶部导航栏

    此笔记纯属本人脑残笔记,阅读困难不理解属正常现象,初学者尽量不要阅读,否则轻则口吐白沫重则走火入魔,切记切记 先晒效果图: 效果要求类似于b站的顶部导航(..原谅我老是拿b站做例子:) ) 然后是代码 ...

  4. Web Service 的工作原理

    Web Service基本概念 Web Service也叫XML Web Service WebService是一种可以接收从Internet或者Intranet上的其它系统中传递过来的请求,轻量级的 ...

  5. 一秒钟看懂SaaS、CRM、OA、ERP、HR、进销存

    自2014年以来,SaaS.CRM.OA.ERP.HR.APM.进销存.财务系统等,这些名词大量出现在微信朋友圈.电视楼宇广告和千百万融资资讯中.它们到底是什么意思?相互之间又有什么区别?在这个飞速发 ...

  6. 利用iframe实现无刷新上传处理

    继上一篇对上传异常进行处理之后,当上传异常的时候的错误体验并不是很好,这里介绍用iframe来进行错误提示 拦截错误 @ExceptionHandler(MaxUploadSizeExceededEx ...

  7. Sql Server之旅——第十三站 对锁的初步认识

    终于这个系列快结束了,马上又要过年了,没什么心情写博客...作为一个开发人员,锁机制也是我们程序员必须掌握的东西,很久之前 在学习锁的时候,都是教科书上怎么说,然后我怎么背,缺少一个工具让我们眼见为实 ...

  8. 最近用Timer踩了一个坑,分享一下避免别人继续踩

    最近做一个小项目,项目中有一个定时服务,需要向对方定时发送数据,时间间隔是1.5s,然后就想到了用C#的Timer类,我们知道Timer 确实非常好用,因为里面有非常人性化的start和stop功能, ...

  9. spring listener监听器

    1.Listener的定义与作用 监听器Listener就是在application,session,request三个对象创建.销毁或者往其中添加修改删除属性时自动执行代码的功能组件. Listen ...

  10. Boost.log

    =================================版权声明================================= 版权声明:本文为博主原创文章 未经许可不得转载  请通过右 ...