函数调用的对象解构
Posted
技术标签:
【中文标题】函数调用的对象解构【英文标题】:Object destructuring for function calls 【发布时间】:2019-09-10 18:29:03 【问题描述】:有没有办法就地解构 JS 对象,而不是将解构后的变量分配给作用域?
不要这样做:
const a, b, c = obj;
someFunction(a, b, c);
我想这样做:
someFunction(a, b, c from obj);
或功能等效的东西。
我想在有这两个规定的情况下这样做:
我不想将变量名放入封闭范围内。
我不想传递整个对象 obj
,因此无法选择展开运算符。
我剩下的唯一选择是使用
someFunction(obj.a, obj.b, obj.c);
在这种情况下这很好,但当obj
是一个长标识符时会降低可读性。
这样的事情可能吗?我尝试在表达式中使用赋值作为解决方法,但我的 IDE 抱怨它找不到名称 a
、b
和 c
:
someFunction(a, b, c = obj);
【问题讨论】:
如果你的目标是 es6 环境,你可以使用解构参数来定义你的函数,例如function f(a,b,c) /*...*/
或者你不想这样,因为你不想传递整个对象
【参考方案1】:
一种选择是使用.map
提取您想要的每个属性的值,并将其传播到参数列表中:
someFunction(
...['a', 'b', 'c'].map(prop => obj[prop])
);
解构需要创建中间变量,不幸的是,这是你不想要的。
【讨论】:
不幸的是,中间体是必需的,因为在某些情况下(比如我的)它只是不必要的性能损失。至于你的提议,我喜欢它比obj.property
更好地扩展,但它仍然很冗长:/ 足以让我确信如果没有代码审查失败,我就无法将它投入生产代码。
性能很少需要担心 - 代码可读性在 99% 的情况下更重要,如果您想保持代码 DRY 并希望能够将模式用于任意数量的属性,我很确定这是你能找到的最好的模式。如果由于过于冗长而导致代码审查失败,我认为这表明代码审查存在问题,而不是此处的代码存在问题
我同意你的所有陈述,尤其是最后一个(但遗憾的是,我的观点并没有胜过传统)。也许我应该试一试,看看会发生什么。【参考方案2】:
IIFE 应该可以工作:
((( a, b, c ) => someFunction(a, b, c))(obj);
【讨论】:
我喜欢这个工作,但我不喜欢每当我需要调用someFunction
时创建函数的性能损失。此外,与另一个答案类似,这看起来很不寻常,我认为它不会通过代码审查:/.【参考方案3】:
我会这样做:
function foo( x, y )
console.log( x, y );
foo( y: 1, x: 2 ); // 2 1
至于 OP 的具体要求是不传递整个对象(或在全局范围内声明变量)。恕我直言,将对象解构为块范围变量是最好的方法。
const obj = x: 1, y: 2
function foo( x, y )
console.log( x, y );
let x, y = obj;
foo( x, y ); // 1 2
console.log(x) // "ReferenceError: x is not defined
【讨论】:
您能解释一下这如何解决我的问题吗?我看不出有很强的关系。 您将对象作为参数传递,并将其作为函数参数进行破坏。我知道您说过您不想将整个对象作为参数传递,这仍然是我的建议。 对,但这意味着我必须是编写函数的人。非常适合我自己的代码,但在很多情况下我无法控制函数的参数,例如库,或为公司编码时的大部分成本。 @@AnthonyMonterrosa 如果这是一个大问题,我会使用这种风格作为你的库调用的包装函数,例如function wrapLib(x, y) return library.expensiveCall(x,y)
。如果情况需要,可以缓存结果。或者,TC39 一直在寻找对 JS 的独特改进。【参考方案4】:
对象解构的函数调用参数未知
当您无法访问或更改函数声明,或者您不想这样做时,这是需要的。
const getParamNames = func =>
const STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
const ARGUMENT_NAMES = /([^\s,]+)/g;
let fnStr = func.toString().replace(STRIP_COMMENTS, '');
let result = fnStr.slice(fnStr.indexOf('(')+1,
fnStr.indexOf(')')).match(ARGUMENT_NAMES);
if (result === null) result = [];
return result;
const callFunctionFromObject = (func, obj) =>
let params = getParamNames2(func)
return func(...params.map(prop => obj[prop]))
示例用法:
//Function declared somewhere:
var logFor*** = (a, b, c) => console.log(a, b, c)
//ex1
callFunctionFromObject(logFor***, a: 1);
1 undefined undefined
//ex2
callFunctionFromObject(logFor***, b: 1)
undefined 1 undefined
//ex3
callFunctionFromObject(logFor***, b: "hello", c:3, a:[1, 2, 3])
[1, 2, 3] "hello" 3
感谢@CertainPerformance。解决方案。 如果您有任何问题,请给我留言。谢谢。
【讨论】:
【参考方案5】:当对象的属性顺序与函数的参数一致时,您可以使用:
someFunction(...Object.values(obj))
【讨论】:
以上是关于函数调用的对象解构的主要内容,如果未能解决你的问题,请参考以下文章
箭头函数 解构赋值 立即执行函数 (function() )()
Kotlin常用的 Kotlin 类 ① ( 嵌套类 | 数据类 | 数据类 copy 函数 | 数据类解构声明 operator fun component1 | 数据类运算符重载 )
Kotlin常用的 Kotlin 类 ① ( 嵌套类 | 数据类 | 数据类 copy 函数 | 数据类解构声明 operator fun component1 | 数据类运算符重载 )