Javascript 还有一个调用vs Apply查询
当我尝试运行以下代码时:Javascript 还有一个调用vs Apply查询,javascript,Javascript,当我尝试运行以下代码时: function flatten(a) { return [].slice.call(arguments).reduce(function(acc, val) { return acc.concat(Array.isArray(val) ? flatten.call(null, val) : val); }, []); } 我得到了以下错误: 未捕获范围错误:超过最大调用堆栈大小 但是如果我使用了flatte.apply而不是flatte.call,它
function flatten(a) {
return [].slice.call(arguments).reduce(function(acc, val) {
return acc.concat(Array.isArray(val) ? flatten.call(null, val) : val);
}, []);
}
我得到了以下错误:
未捕获范围错误:超过最大调用堆栈大小
但是如果我使用了flatte.apply
而不是flatte.call
,它就可以完美地工作。(深度展平输入阵列)
除此之外,我很少阅读其他博客和文章来理解它为何如此。我要么找不到答案,要么我一定是忽略了。(如果是后一种情况,请原谅我的怒视)
当然,这二者之间的根本区别在于:
应用-要求可选参数为数组
调用-要求显式列出可选参数
通常,函数可以采用任何类型的参数—原语和非原语。因此,我的问题是:
Array
类型还是其他非基本类型
call
时,为什么上面的代码超过了调用堆栈
编辑:因为使用了2种
call
方法,所以我的描述不明确。我做了一些更改来澄清。当您调用flatte.call(null,val)
时,val
是一个数组,flatte
函数作为参数val
接收您作为可选参数传递给call
(类型未选中),因此参数
是[val]/code>
您可以看到val
数组位于数组中。当您调用reduce
时,回调中的val
仍将是一个数组,您什么也没有展平,这就是它从不停止的原因
调用flatte.apply(null,val)
时,val
是一个数组,flatte
函数作为参数接收val
的元素,因此参数与val
相同(不是[val]
):您已经有效地打开了数组。这就是它工作的原因。您的错误在这里:
[].slice.call(arguments).reduce
^^^^^^^^^
因此,当您通过[x]
时,您在[[x]]
上调用reduce
,第一个val
变为[x]
。然后您再次使用[x]
调用flatten
,故事就会重复
另一方面,apply(…,val)
只将x
传递到flatten
,从而将嵌套级别降低一级
如果您对如何使用apply
展平深度嵌套数组感兴趣,则无需递归即可:
while(ary.some(Array.isArray))
ary = [].concat.apply([], ary);
下面是call
vsapply
的一个小例子:
函数fun(){
var len=arguments.length;
文档。写“我有”
+莱恩
+ " "
+(len>1?“参数”:“参数”)
+ ": "
+stringify(参数)
+“
”;
}
fun.call(null,123);
//fun.apply(null,123);谢谢@georg。这就澄清了这一点。这意味着,call()可以通过一个非原语参数作为其可选参数进行传递-我说的对吗?而非递归的深层扁平化代码-太棒了!谢谢你,朋友@Harish:添加了调用vs应用的示例