• 永远不要修改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个有效方法

  • 相关阅读:
    团队项目冲刺七
    团队项目冲刺六
    团队项目冲刺5
    团队项目冲刺4
    团队项目测试计划
    团队项目冲刺第三天进度和遇到问题
    团队项目冲刺第二天进度和问题
    博客园用户体验
    团队项目冲刺第一天进度和问题
    团队项目风险
  • 原文地址:https://www.cnblogs.com/mackxu/p/arguments.html
Copyright © 2020-2023  润新知