说我有这个功能:
function doSomething(uno, dos, tres) {
// do something
}
和这个对象:
{
dos: 'foo',
tres: 'bar',
uno: 'baz'
}
如果给出此映射,如何调用doSomething
?我尝试使用apply
,但似乎apply
必须采用列表而不是对象。
答案 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
答案 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);