我正在修改某些"核心"的几个功能。 JS软件使用"劫持":
var orig_func = func; // initially function(a,b,c,d)
func = function(a,b,c,d) {
// modify arguments
d = someCustomization(c,d);
// do additional stuff
doSomethingCustom(a);
// apply the original "core" function
return orig_func.apply(this,arguments);
}
除非修改后的参数是可选的,否则可以正常工作:调用
func(a,b);
以d
为undefined
的方式工作,即使someCustomization
在其参数均为undefined
时返回其他内容。
这是一个在cosole中使用的MVCE:
var f = function(optionalParam){ if(optionalParam) console.log(optionalParam); };
var orig_f = f;
f = function(optionalParam){
optionalParam = optionalParam ? 'custom: '+optionalParam : 'default';
orig_f.apply(this, arguments);
};
f(); // shows undefined
f('test'); // shows 'custom: test'
"预期"行为是在第一种情况下在控制台中查看"default"
,但我得到的是undefined
。
经过一些实验并使用this thread,我总结了在corresponding answer中添加定位参数的问题,我提出了以下MCVE方案:
var f = function(some,optionalParam){
console.log('some:',some);
console.log('optionalParam:',optionalParam);
};
var orig_f = f;
f = function(some,optionalParam){
if(optionalParam)
optionalParam = 'custom: '+optionalParam;
else {
var argPosition = 2;
while(arguments.length < argPosition)
[].push.call(arguments,undefined);
arguments[argPosition-1] = 'default';
}
orig_f.apply(this, arguments);
};
f(); // shows 'some: undefined' and 'optionalParam: default'
或就初始任务而言:
var orig_func = func; // initially function(a,b,c,d)
func = function(a,b,c,d) {
// modify arguments
while(arguments.length < 4)
[].push.call(arguments,undefined);
arguments[3] = someCustomization(c,d);
// do additional stuff
doSomethingCustom(a);
// apply the original "core" function
return orig_func.apply(this,arguments);
}
但我真的无法解释初始方法的问题是什么:为什么它适用于所需(使用过的)参数并且对于可选(未使用)参数失败?它与闭合有什么关系吗?为什么d
是&#34;没有连接&#34;在第二种情况下使用arguments
?
答案 0 :(得分:3)
arguments
&#34;魔法绑定&#34;是通过迭代实际参数创建的,因此如果不存在arg,则不会创建任何绑定:
function a(x, y) {
y = 42;
console.log(arguments)
}
a(10, 20)
a(10)
&#13;
也就是说,使用魔术绑定是一个坏主意,他们无论如何都不会在严格模式下工作。如果事先知道参数的数量,只需执行
orig_func.call(this, a, b, c, d);
否则使用splat ...args
并操纵它。
答案 1 :(得分:0)
是的,在georg(“魔术绑定”关键字)和更多研究的帮助下,我得出了一个几乎足够的解释:
(未找到哪一个)参数变量(a,b,c,d
)和arguments[i]
指向相同的值(不知道如何在JS 中完成这项工作,但是)
在 new 标准中并非如此(如Bergi所说,已弃用):更改arguments[0]
不会影响a
,反之亦然;就像乔治所说的那样,严格模式是这样的:
function f(x) {
"use strict";
arguments[0] = 5;
console.log( x );
}
f(1); // logs 1
现在当所有变量都存在时,a,b,c,d
(作为作用于函数的变量)和arguments[1-4]
都被定义并成对连接,指向相同的值。当段落c
和d
被省略时,arguments[3]
和arguments[4]
未定义,即使我们定义它们,它们与变量之间也没有“连接”(同样,我不确定是否可以手动创建此类连接)
arguments
(和.apply
它们)或仅使用局部变量(并使用.call
)或混合使用但不要不依赖于他们之间的联系