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

  • 相关阅读:
    go 学习笔记---chan
    golang学习笔记---Goroutine
    golang ---Learn Concurrency
    golang ----并发 && 并行
    golang 学习笔记 使用cmd
    并发程序与并行程序
    golang学习笔记 ---interface
    golang --- map如何判断key是否存在
    golang学习 ---defer语句
    golang --for语句
  • 原文地址:https://www.cnblogs.com/mackxu/p/arguments.html
Copyright © 2011-2022 走看看