如何获取回调函数的所有参数

23

经常情况下,我使用回调函数时没有相关的文档,能够看到传递给该回调函数的所有参数是非常好的。

// callback is a function that I don't know the args for...
// and lets say it was defined to be used like: callback(name, number, value)
something.doSomething( callback );

我该如何确定它传递了哪些参数?

注意:查看源代码可能无法提供帮助,因为代码本身可能是混淆和压缩的(例如许多JS框架)。


4
arguments 是 JavaScript 中的一个特殊对象,它包含了函数被调用时传入的所有参数。arguments 对象具有类似数组的属性,可以通过索引来访问每个参数。同时,arguments 对象也拥有一个 length 属性,表示传入参数的数量。在 ES6 引入剩余参数语法后,使用 arguments 的场景逐渐减少。但是,在需要灵活处理参数的情况下,arguments 仍然是一种有用的选择。需要注意的是,arguments 对象只存在于函数内部,并且无法在箭头函数中使用。 - asawyer
1
参数应该由被调用者定义,而不是调用者? - jbabey
即使您没有文档,通常也可以查看调用函数的源代码。 - hugomg
4个回答

34

为了获取参数列表而不破坏功能,请以这种方式重写回调函数:

var original = callback;
callback = function() {
    // Do something with arguments:
    console.log(arguments);
    return original.apply(this, arguments);
};
  1. 上下文this)被保留。
  2. 所有参数正确传递。
  3. 返回值正确传递。

注意:此方法在大多数情况下有效。但是有些边缘情况下,此方法会失败,包括:

  • 只读属性(例如使用 Object.defineProperty 定义并使用 writable:false
  • 使用 getter/setter 定义的属性,在 getter/setter 不对称时。
  • 主机对象和插件 API:例如 Flash 和 ActiveX。

1
PS. 为了获取更多详细信息,请在替换的回调函数中添加console.trace(); - Rob W
1
为什么 return original.apply(this, arguments); 不够用? - gdoron
2
@RobW:如果您说的是以“注意”开始的注释:“大多数浏览器(包括Chrome 14和Internet Explorer 9...)”,那么它并不适用于Arguments对象。 我不知道是否有任何浏览器不接受Arguments对象作为.apply()的第二个参数。 顺便说一下,这在Chrome中最近得到了修复,因此任何类似数组的对象都可以工作。 - user1106925
1
@amnotiam。"关于_apply_的注释不适用..." 人类语言在最好的状态下。**:-)** - gdoron
2
@gdoron:确实。 :) 顺便说一下,我刚在IE6中验证了这一点。Arguments对象可以毫无问题地被.apply()接受。 - user1106925
显示剩余5条评论

8

它可能如此简单,就像

function callback() {
    console.log(arguments);
}

每个函数都在自动创建的arguments集合中提供了调用它时所带的参数。


他无法更改回调代码。如果他能够更改,他就不需要使用参数来知道它的参数是什么了... - gdoron
他在哪里说的?你从什么时候开始不能更改JS代码了?除此之外,JS调试器和断点只需点击几下即可。 - Tomalak
他写道他不想看函数的文档,所以他肯定没有手头上的那个函数代码... - gdoron
2
在代码中添加 console.log(this),你就可以完整地查看本地作用域。 - John Strickler
这是处理被压缩/混淆的代码时经常遇到的问题…例如任何 jQuery/MooTools/等等内容。 - Kristian
@gdoron 我不知道你怎么想,但我通常都会把我正在使用的所有JS代码准备好。 ;) 另外,回调函数是我编写的函数。如果我当前没有编写该函数,为什么要关心参数呢? - Tomalak

1

这不是本末倒置吗?

你的函数接受一个回调函数。使用你的函数的方法应该知道回调函数应该接受什么参数。


7
如果这是我的函数,那将是正确的,但因为你巧妙地使用了斜体字,我给你加一分。哈哈 ;) - Kristian

0

您甚至可以使用[函数名].arguments指定要获取哪个函数的参数:

(function(arg1, arg2, agr3){
    console.log('args are:', arguments);
    return function fn(){
        function m(){
            console.log(
                'fn.arguments:', fn.arguments,
                'm.arguments:', m.arguments,
                'argumentsX:', arguments
            );
        };
        m('mArg1', 'mArg2', 'mArg3', 'mArg4');
    };
})
(1, 2, Math.PI)  // invoke closure
('fnArg1', 'fnArg2', 'fnArg3', 'fnArg4');  // invoke "fn"

每个函数定义都会将参数关键字重写为该作用域的关键字(如"argumentsX"日志所示)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接