我正在尝试在javascript中更改函数参数。
f = function(){
console.log(a,b,c);
};
SetArgumentList( f, ["a", "b", "c"] );
f(1,2,3);
// should print "1 2 3"
// [edit]
// alternatively SetArgumentList could also work like
f = SetArgumentList( f, ["a", "b", "c"] );
有没有坚实的方法呢?
我在哪里需要它?...基本上我正在尝试添加类型检查功能:
Object.prototype.method = function( name, typedef, func ){ ... }
function Thing(){};
Thing.method("log",
{ arr: Array, str: String },
function(){
console.log(arr, str);
});
t = new Thing();
t.log([1,2,3], "ok");
t.log("err", "ok"); // <-- causes an exception
// I know I can do this way
Thing.method("log",
[Array, String],
function(arr, str){
console.log(arr, str);
});
// but that's harder to read
请注意!我知道如何进行类型检查,但不知道新的函数构造。
答案 0 :(得分:2)
正如德尔南在评论中所说,你想要做的似乎是“重命名”函数本地的变量。就像他说的那样,这是不可能的(也是有充分理由的!你能想象调试吗?maaan ......)
无论如何,我不确切地知道为什么你想要它,但是Javascript是一种灵活的语言,你可能会使用一个更理智的方法来接近。很难确切知道你想要达到的目标,但也许这些信息可能会让你走上正轨:
在调用时传递给函数的参数在名为arguments
的变量中引用。
function f() {
console.log(arguments);
}
f(); // []
f(1, 2); // [1, 2]
您可以使用.apply
调用具有任意参数列表的函数,this
是函数原型的一个方法。它需要2个参数。第一个是函数调用中的f.apply(null, []); // []
f.apply(null, [1, 2, 3]); [1, 2, 3]
对象,第二个是参数数组。
function f() {
console.log.apply(console, arguments);
}
在你的情况下应用这个,也许这就是你所追求的:
{{1}}
答案 1 :(得分:1)
在IE7,8,9,opera,chrome,firefox和safari中测试过。在后台使用evil
,但是
如果你必须重命名参数,我看不到任何其他方式。
(function(){
var decompileRE = /function\s*\([\s\S]*?\)\s*\{([\s\S]*)/,
lastBrace = /\}[^}]*$/;
window.SetArgumentList = function( fn, argNames ) {
var match
if( !( match = fn.toString().match( decompileRE ) ) ) {
return fn;
}
argNames.push( match[1].replace( lastBrace, "" ) );
return Function.apply( null, argNames );
};
})()
f = function(){
console.log(a,b,c);
};
f = SetArgumentList( f, ["a","b","c"] );
console.log(f);
在上述所有浏览器中记录此内容:
function anonymous(a,b,c) {
console.log(a,b,c);
}
答案 2 :(得分:1)
我有一个更简单的解决方案,类似于那些正在寻找的人接受的答案。适用于Chrome,Firefox,Safari,IE7 +
function SetArgList(fn, args) {
var fnbody = fn.toString().replace(
/^\s*function\s*[\$_a-zA-Z0-9]+\(.*\)\s*\{/, //BEWARE, removes original arguments
''
).replace(
/\s*\}\s*$/,
''
);
return new Function(args, fnbody)
}
只需使用SetArgList重新定义原始函数:
function main() {
alert(hello);
alert(world);
}
main = SetArgList(main, 'hello,world');
main('hello', 'world');
在我的解决方案中,不需要数组但你可以编辑它,我的函数只需要用逗号分隔的参数名称。
答案 3 :(得分:0)
你可以使用.apply: 这对我有用:
f = function(a,b,c){
console.log(a,b,c);
};
var args = ["a", "b", "c"];
f.apply(this, args); //print "abc"
使用参数:
f = function(){
for(var key in arguments) {
console.log(arguments[key]);
}
};
var args = ["a", "b", "c"];
f.apply(this, args);
你在寻找吗?
答案 4 :(得分:0)
我找到了一个仅适用于webkit浏览器的解决方案:
f = function(){ console.log(a,b,c); };
fx = eval(
f.toString().replace(
/^function [^\(]*\(\)/,
"var __temp = function (a,b,c)")
+ "; __temp");
fx(1,2,3);
这也可以概括。
[编辑]
这也适用于其他浏览器,内存让我失望 - 某些浏览器中的评论// /**/
被丢弃。
答案 5 :(得分:0)
如前所述,你不能按你想要的方式去做,你正在打破词汇范围。 但是,这里有一个极简主义版本的实现方式(应该做很多改进!)。唯一需要的是你的函数在参数中有命名参数。
function getType( el ) {
// TODO
return "";
}
function addMethod( obj, name, typedef, func ) {
var argumentsLength = typedef.length;
obj[ name ] = function() {
var len = arguments.length, i = 0;
if( argumentsLength != len )
{
throw new TypeError( "Wrong number of arguments for method " + name );
}
for( i = 0; i < len; i++ )
{
// TODO better type checking
if( getType( arguments[i] ) != getType( typedef[i] ) )
{
throw new TypeError( "Wrong type for arguments number " + i + " for method " + name );
}
}
return func.apply( obj, arguments );
};
};
var o = {};
addMethod( o, "log", [Array, String], function( arr, str ) {
// arguments MUST be explicitly declared above
console.log( arr, str );
});
o.log( ["a"], "b" ); // OK
o.log( "a", "b" ); // TypeError
o.log( ["a"], "b", "c" ); // TypeError