如何使用JS数组元素定义使用参数对函数的调用

How to Use JS Array Elements to Define Calls to Functions Using Arguments

本文关键字:参数 函数 调用 何使用 JS 数组元素 定义      更新时间:2023-09-26

对于这个特定的应用程序,我在折线图上绘制点,这些是我的函数用来将点放置在直线上正确位置的数字。

var CustomData = [
  [168,36,10,1,"#FFFFFF","#f0e58d"],
  [282,31,10,1,"#FFFFFF","#559ab5"],
  [338,47,10,1,"#FFFFFF","#f0e58d"],
  [448,55,10,1,"#FFFFFF","#559ab5"],
  [540,49,10,1,"#FFFFFF","#559ab5"],
  [674,27,10,1,"#FFFFFF","#f0e58d"],
  [718,24,10,1,"#FFFFFF","#559ab5"],
  [846,24,10,1,"#FFFFFF","#f0e58d"],
  [1008,35,10,1,"#FFFFFF","#f0e58d"]
];

这些值的描述:

CustomData[index][x, y, radius, lineWeight, lineColor, fillColor];

我正在做的是使用CreateJS库来绘制这些形状,并使用简单的事件侦听器来检测点击事件(为清晰起见,虚线):

for(i = 0; i < this.CustomData.length; i ++) {
  var _i = this.CustomData[i];
  this.NewShape = new cjs.Shape();
  this.NewShape.set({cursor:"pointer"});
  this.NewShape.graphics.ss(_i[3]);
  this.NewShape.graphics.s(_i[4]);
  this.NewShape.graphics.f(_i[5]);
  this.NewShape.graphics.dc(_i[0],_i[1],_i[2]);
  (function(i,shape,_i){
    shape.on("click", function() { DoStuff(i,_i); });
  })(i,this.NewShape,_i);
  this.addChild(this.NewShape);
}

我想做的是扩展这个例程,这样我就可以在每个形状上使用一个自定义函数,我只是不知道如何在数组中定义对函数的引用。我还需要能够将迭代和CustomData元素传递到函数中。

理论上,我想象的是:

var CustomData = [
  [168,36,10,1,"#FFFFFF","#f0e58d", "DataFunc_A" ],
  [282,31,10,1,"#FFFFFF","#559ab5", "DataFunc_B" ],
  [338,47,10,1,"#FFFFFF","#f0e58d", "DataFunc_A" ],
  [448,55,10,1,"#FFFFFF","#559ab5", "DataFunc_B" ],
  [540,49,10,1,"#FFFFFF","#559ab5", "DataFunc_B" ],
  [674,27,10,1,"#FFFFFF","#f0e58d", "DataFunc_A" ],
  [718,24,10,1,"#FFFFFF","#559ab5", "DataFunc_B" ],
  [846,24,10,1,"#FFFFFF","#f0e58d", "DataFunc_A" ],
  [1008,35,10,1,"#FFFFFF","#f0e58d", "DataFunc_A" ]
];

并将循环中的匿名函数更改为:

(function(i,shape,_i){
  shape.on("click", function() {
    window[_i[6]](i,_i);
  });
})(i,this.NewShape,_i);

我的问题是:这是实现这一目标的最佳、可扩展的方式吗?我需要记住什么"窍门"吗?提前谢谢。

这是实现这一目标的最佳、可扩展的方式吗?

我不知道可伸缩,但这不是实现这一点的最佳方式。

我需要记住什么"窍门"吗?

通过将字符串存储在数组中,然后稍后在window对象上查找这些字符串,您就迫使自己将所有函数设为全局函数。全局命名空间已经非常非常拥挤,这导致了冲突的可能性。你在全局命名空间中放的越多,你遇到的冲突就越多。

相反:

您可以像其他任何值一样将函数放置在数组中,因为函数可以通过表达式创建:

var CustomData = [
  [168,36,10,1,"#FFFFFF","#f0e58d", function() { /* do something */ }],
  [282,31,10,1,"#FFFFFF","#559ab5", function() { /* do something else */ }],
  [338,47,10,1,"#FFFFFF","#f0e58d", function() { /* do yet another thing */ }],
  // ...
];

如果你需要在多个条目上使用同一个函数,或者如果你遇到可读性或维护问题,使用这样的内联定义的长函数,你可能会发现单独定义函数,然后在数组中引用它们更有用:

var CustomData = [
  [168,36,10,1,"#FFFFFF","#f0e58d", doSomething],
  [282,31,10,1,"#FFFFFF","#559ab5", doSomethingElse],
  [338,47,10,1,"#FFFFFF","#f0e58d", doYetAnotherThing],
  // ...
];
function doSomething() {
    // ...
}
function doSomethingElse() {
    // ...
}
function doYetAnotherThing() {
    // ...
}

即使在第二种情况下,如果您的代码位于作用域函数或模块(无论是某种形式的库AMD还是ES2015模块)中,这些函数也不会是全局函数。(如果你只是在全局范围内,而不是在scping函数或模块中,它们就会出现。)

你可以像调用其他函数一样调用这些函数:

_i[6](arg1, arg2, arg3);

这里我使用6,因为在上面的例子中,这些函数在每个数组中的索引为6。


说了这么多,我建议您考虑使用对象而不是数组作为CustomData数组中的条目。

从你的问题中考虑这个代码:

this.NewShape.set({cursor:"pointer"});
this.NewShape.graphics.ss(_i[3]);
this.NewShape.graphics.s(_i[4]);
this.NewShape.graphics.f(_i[5]);
this.NewShape.graphics.dc(_i[0],_i[1],_i[2]);

与。,比如说,这个:

this.NewShape.set({cursor:"pointer"});
this.NewShape.graphics.ss(_i.ss);
this.NewShape.graphics.s(_i.s);
this.NewShape.graphics.f(_i.f);
this.NewShape.graphics.dc(_i.dc[0],_i.dc[1],_i.dc[2]);

你可以这样做:

var CustomData = [
  {dc: [168,36,10], ss: 1, s: "#FFFFFF", f: "#f0e58d", func: doSomething},
  {dc: [282,31,10], ss: 1, s: "#FFFFFF", f: "#559ab5", func: doSomethingElse},
  {dc: [338,47,10], ss: 1, s: "#FFFFFF", f: "#f0e58d", func: doYetAnotherThing},
  // ...
];

使用符号(ss, s , f , dc`)而不是索引通常会使事情随着时间的推移更容易维护。更长、更有意义的名称可能更有用。


关于创建带有方法的对象以及避免使用全局变量的问题,可以做一件相当标准的事情:

(function() {
    var stuff = {
        data: "Some value",
        method1: function() {
            // Do something, can reference data as `stuff.data`, e.g.:
            console.log(stuff.data);
            // If method1 is called via `stuff` (e.g., `stuff.method1()`),
            // it can also use `this.data`:
            console.log(this.data);
        },
        method2: function() {
            // Do something else...
        }
    };
    var otherStuff = {
        data: "Some other value",
        method3: function() {
            // Do something entirely different, possibly call `stuff.method2`:
            stuff.method2();
        }
    };
    // A standalone utility function
    function utilityFunction(arg) {
        return arg.toUpperCase();
    }
    stuff.method1();
    stuff.method2();
    otherStuff.method3();
})();

最外层的匿名函数是作用域函数,将其中声明的内容保持为私有。stuffmoreStuffutilityFunction都在该函数的范围内,但不在该函数之外

有时你可能会这样做,但想要暴露一个符号(这通常被称为"暴露模块模式",因为你只暴露你想要暴露的东西:

var stuff = (function() {
    // ...all that stuff above...
    return stuff;
})();

ES2015使这些方法声明更加简洁:

// ES2015 (aka ES6) and higher
var stuff = {
    method1() {
        // Do things here...
    }
};

等等。