永远不要修改arguments对象

案例复现

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个有效方法

转载于:https://www.cnblogs.com/mackxu/p/arguments.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值