zoukankan      html  css  js  c++  java
  • 永远不要修改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个有效方法

  • 相关阅读:
    单元测试之NUnit
    “Oracle.DataAccess.Client.OracleConnection”的类型初始值设定项引发异常
    功能强大的树状结构TreeGrid
    右键效果图
    可视化定义工作流(正在努力做......w)
    关于自动发送邮件换行等问题解决
    清空Cache
    .net发生类型为 System.OutOfMemoryException 的异常解决办法
    再谈xml
    Delphi日期函数大全
  • 原文地址:https://www.cnblogs.com/mackxu/p/arguments.html
Copyright © 2011-2022 走看看