当我尝试运行以下代码时:
function flatten(a) {
return [].slice.call(arguments).reduce(function(acc, val) {
return acc.concat(Array.isArray(val) ? flatten.call(null, val) : val);
}, []);
}
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:
未捕获RangeError:超出最大调用堆栈大小
但如果我使用flatten.apply而不是flatten.call,它的工作完美.(深度压平输入数组).
除了这个link1和link2之外,我还阅读了其他一些博客和文章,以了解其行为的原因.我要么找不到答案,要么就是忽略了它.(原谅我的眼睛,如果在后一种情况下)
当然,这两者之间的根本区别在于:
apply - 要求可选参数为数组
call - 要求显式列出可选参数
通常,函数可以采用任何类型的参数 - 基元和非基元.所以,我的问题是:
调用方法的可选参数之一可以是类型Array还是其他非基本类型?
为什么上面的代码超过了调用堆栈,何时call使用?
编辑:由于call使用了2 种方法,我的描述含糊不清.我做了修改以澄清.
你的错误在这里:
[].slice.call(arguments).reduce
^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)
所以,当你通过[x],你调用reduce上[[x]]和第一val变[x].然后你flatten再次打电话[x],故事重演.
另一方面,apply(..., val)将仅传递x给flatten,从而将嵌套级别减少一个.
如果您对如何使用apply扁平深层嵌套数组感兴趣,可以不使用递归:
while(ary.some(Array.isArray))
ary = [].concat.apply([], ary);
Run Code Online (Sandbox Code Playgroud)
这是callvs 的一个小例子apply:
function fun() {
var len = arguments.length;
document.write("I've got "
+ len
+ " "
+ (len > 1 ? " arguments" : "argument")
+ ": "
+ JSON.stringify(arguments)
+ "<br>");
}
fun.call(null, 123);
// fun.apply(null, 123); <-- error, won't work
fun.call(null, [1,2,3]);
fun.apply(null, [1,2,3]);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
50 次 |
| 最近记录: |