猿问

在接受数字或数组作为 args 的函数中,如何有效地操作这些 args 而不管类型如何?

假设您有一个函数,它接受 1D 坐标、2D 坐标或 3D 坐标作为参数。在函数调用时,如果用户想传递一些一维坐标,他们会传递简单的数字,例如:


myFunction(30, 50);

但是如果他们想传递 2D 或 3D 坐标,他们会将这些坐标作为数组/向量值传递,例如:


myFunction([30, 40], [50, 60]);

现在,在函数定义中,假设您要运行涉及传递的坐标的各种操作和方程。因为您需要处理两种不同的 arg 类型(数字与数组)中的一种,所以您可能希望针对每种数据类型对语句进行不同的格式化,因此最终可能会重复一堆语句,这是低效的。为了论证起见,假设您不能对数组 args 进行简单的向量数学运算,而是需要循环并按索引将它们分解:


function myFunction( coord1, coord2 ) {

    let myVar1 = 0, myVar2 = 0, myVar3 = 0;


    // if args are arrays

    if ( Array.isArray( coord1 ) ) {

        myVar1 = [], myVar2 = [], myVar3 = [];


        for (let i = 0; i < coord1.length; i++) {

            myVar1[i] = coord1[i] * coord2[i];

            myVar2[i] = myVar1[i] / coord2[i] + myVar1[i];

            myVar3[i] = coord1[i] * (coord2[i] / myVar2[i]);

        }


    // else if args are scalar

    } else {

        myVar1 = coord1 * coord2;            // this

        myVar2 = myVar1 / coord2 + myVar1;   // is

        myVar3 = coord1 * (coord2 / myVar2); // inefficient

    }


    return myVar3;

}

上面的等式是无稽之谈,但它们只是为了说明。您将如何避免在这里重复自己?我可以想到几种 DRY 方法(将标量 args 分配给单索引数组;或者将大块的方程变成混乱且难以阅读的“逻辑或”表达式(例如,myVar[i] = (coord1[i] || coord1) * (coord2[i] || coord2));或者装配一个对象数组或者什么),但我真的不喜欢其中任何一个,而且我还是个新手,所以我不知道它是什么我不知道。任何有经验的编码人员都想权衡处理这种情况的最佳实践吗?


开满天机
浏览 148回答 3
3回答

慕神8447489

对于逐元素重复,只需让数组函数调用标量函数:function myFunctionArr(coords1, coords2) {&nbsp; &nbsp; const results = [];&nbsp; &nbsp; for (let i = 0; i < coords1.length; i++) {&nbsp; &nbsp; &nbsp; &nbsp; results[i] = myFunctionScalar(coords1[i], coords2[i]);&nbsp; &nbsp; }&nbsp; &nbsp; return results;}function myFunctionScalar(coord1, coord2) {&nbsp; &nbsp; const myVar1 = coord1 * coord2;&nbsp; &nbsp; const myVar2 = myVar1 / coord2 + myVar1;&nbsp; &nbsp; return coord1 * (coord2 / myVar2);}当然你也可以把它变成一个重载函数,比如function myFunction(coord1, coord2) {&nbsp; &nbsp; if (Array.isArray(coord1)) { // args are arrays&nbsp; &nbsp; &nbsp; &nbsp; return myFunctionArr(coord1, coord2);&nbsp; &nbsp; } else { // args are scalar&nbsp; &nbsp; &nbsp; &nbsp; return myFunctionScalar(coord1, coord2);&nbsp; &nbsp; }}您甚至可以在辅助函数(也由许多具有功能的库提供)中的多个数组元素上抽象函数的元素应用:return zipWith(myFunctionScalar, coords1, coords2)

慕田峪9158850

如果您的泛型函数应该始终具有同构参数和返回类型,那么首先仅使用原语为您的函数定义基本情况,然后使用包装函数遍历您的参数并将您的基本情况函数应用于每个元素:function myFunction (coord1, coord2) {&nbsp; const myVar1 = coord1 * coord2;&nbsp; const myVar2 = myVar1 / coord2 + myVar1;&nbsp; return coord1 * (coord2 / myVar2);}function generic (f) {&nbsp; return function g (x, ...args) {&nbsp; &nbsp; return Array.isArray(x)&nbsp; &nbsp; &nbsp; ? x.map((el, i) => g(el, ...args.map(arg => arg[i])))&nbsp; &nbsp; &nbsp; : f(x, ...args);&nbsp; };}const myGenericFunction = generic(myFunction);console.log(myGenericFunction(30, 50));console.log(myGenericFunction([30, 40], [50, 60]));console.log(myGenericFunction([[30, 40], [70, 80]], [[50, 60], [10, 20]]));

弑天下

定义每个方程的函数。function myFunction( coord1, coord2 ) {&nbsp; &nbsp; // Equations&nbsp; &nbsp; let e1 = (a,b) => {return a * b;}&nbsp; &nbsp; let e2 = (a,b,c) => {return a * b + c;}&nbsp; &nbsp; let e3 = (a,b,c) => {return a * (b / c);}&nbsp; &nbsp; let myVar1 = 0, myVar2 = 0, myVar3 = 0;&nbsp; &nbsp; // if args are arrays&nbsp; &nbsp; if ( Array.isArray( coord1 ) ) {&nbsp; &nbsp; &nbsp; &nbsp; myVar1 = [], myVar2 = [], myVar3 = [];&nbsp; &nbsp; &nbsp; &nbsp; for (let i = 0; i < coord1.length; i++) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; myVar1[i] = e1(coord1[i], coord2[i]);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; myVar2[i] = e2(myVar1[i],coord2[i],myVar1[i]);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; myVar3[i] = e3(coord1[i],coord2[i],myVar2[i]);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; // else if args are scalar&nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; myVar1 = e1(coord1,coord2);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // this&nbsp; &nbsp; &nbsp; &nbsp; myVar2 = e2(myVar1,coord2,myVar1);&nbsp; &nbsp;// is&nbsp; &nbsp; &nbsp; &nbsp; myVar3 = e3(coord1,coord2,myVar2); // inefficient&nbsp; &nbsp; }&nbsp; &nbsp; return myVar3;}
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答