在给定变量到值的映射的情况下,如何调用javascript函数?

时间:2013-06-05 00:30:16

标签: javascript

说我有这个功能:

function doSomething(uno, dos, tres) {
    // do something
}

和这个对象:

{
    dos: 'foo',
    tres: 'bar',
    uno: 'baz'
}

如果给出此映射,如何调用doSomething?我尝试使用apply,但似乎apply必须采用列表而不是对象。

5 个答案:

答案 0 :(得分:3)

您可以使用下面给出的.来引用上面给出的对象中的每个属性。

doSomething(obj.uno, obj.dos, obj.tres)

答案 1 :(得分:1)

Function.apply只能用于将类似数组的对象 1 应用于函数调用。没有相当于Pythons"关键字参数扩展"这必须手动完成:

var opts = {
    dos: 'foo',
    tres: 'bar',
    uno: 'baz'
}
doSomething(opts.uno, opts.dos, opts.tres)

如果我们开始使用类似数组的对象:

var arr = ['baz', 'foo', 'bar']
doSomething.apply(window, arr)

或者将两者放在一起(以便可以更早地处理参数序列的组成):

var arr = [opts.uno, opts.dos, opts.tres]
doSomething.apply(window, arr)

虽然可能可以(使用非混淆代码)使用Function.toString 2 来提取参数名称,然后进行一些解析,然后再写一些代码"申请"一般对象(或构造随后应用的数组),ECMAScript规范不直接支持。


1 类似数组的对象是具有length和名为0..length-1的属性的对象。 (旧版本的FF有一个错误,但已经修复了很长时间。)

2 规范的措辞("返回函数的依赖于实现的表示。此表示具有FunctionDeclaration的语法。")让我相信一致的ES5实现应该应该生成可用于此目的的输出 - 但是,这可能因实现而异,我还没有在实践中探讨这种用法。

答案 2 :(得分:1)

您可以尝试使用:

function doSomething() {
   for (var i = 0, l = arguments.length; i<l; i++) {
      //dosomething
      console.log(arguments[i]);
   }
}

obj=['foo', 'bar', 'baz'];
doSomething.apply(null, obj);

应用接受数组作为第二个参数但是 如果您坚持使用对象,则可以轻松地将此对象转换为Array,然后将其与apply一起使用。

function objectToArray(obj) {
   var arr = [];
   for (field in obj) 
      arr.push(field);
   return arr;
}

答案 3 :(得分:0)

您可以这样做:

Function.prototype.applyNamed = function (g, argArr) {
    var self = this;    
    var argNames = self.toString().match(/function\s+\w*\s*\((.*?)\)/)[1].split(/\s*,\s*/);
    var applyArgs = [];
    for(var i=0; i<argNames.length; i++){        
        applyArgs.push(argArr[argNames[i]]);        
    }
    self.apply(self, applyArgs);
}

function doSomething(uno, dos, tres) {    
    console.log('uno = ' + uno);
    console.log('dos = ' + dos);
    console.log('tres = ' + tres);
}

var namedArgs = {
    dos: 'foo',
    tres: 'bar',
    uno: 'baz'
};

doSomething.applyNamed(this, namedArgs);

应打印:

uno = baz  
dos = foo  
tres = bar

demo; credit

答案 4 :(得分:0)

好吧,如果你真的想,你实际上可以使用命名参数调用方法,但它需要解析函数的字符串表示。你是否应该使用这种技术是值得商榷的,但是你可以这样做:

function doSomething(uno, dos, tres) {
    // do something
}

var arguments = {
    dos: 'foo',
    tres: 'bar',
    uno: 'baz'
}

function callFunction(fn, namedArguments) {
    var orderedArguments = [];
    var parameterRegExp = /\(([\s\w\$,]*)\)/;

    parameterRegExp.exec(fn.toString())[1].replace(/\s/g, '').split(',').forEach( function(parameterName) {
        orderedArguments.push(namedArguments[parameterName]);
    });

    return fn.apply(this, orderedArguments);
}

callFunction(doSomething, arguments);