如何使用map()来调用对象列表常用的方法?

时间:2015-07-26 02:57:19

标签: javascript arrays object

TL; DR:基本上,我尝试使用Array.prototype.map()来调用上下文对象列表中常用的方法。

说我有这样的代码:

a.doSomething();
b.doSomething();
c.doSomething();
d.doSomething();
e.doSomething();
...

这太过于冗长。我希望能够将此代码缩短为类似的内容

[a, b, c, d, e].map(doSomething);

因为我不想使用for循环。

我如何使用JS中的原生map函数,没有任何外部库来执行此操作?

提前谢谢!如果这篇文章太长,我会很乐意编辑它。只是尖叫着我。

相关问题:

How to use map() to call class methods on a list of objects

How to call same method for a list of objects?

我没有在相关问题中使用这些信息,因为Python和JS使用不同的范例,我不能确保他们的工作方式相同。如果我在这里错了,请不要犹豫,把我烧死。

额外信息,如果您愿意,请忽略

already RTFM,并且措辞和示例表明我无法通过map执行上述操作。 MDN文档将map描述为"在 中调用提供的函数 数组中的每个元素",而MSDN文档说明" 34;在数组的每个元素上调用函数 ,并返回一个数组。"我没有尝试在数组上调用方法,我试图从几个上下文对象中调用方法。如果这不可能,是否有原生的polyfill?

我在游戏中使用它,所以速度是我的主要关注点。如果有更优化的方式来编码,请告诉我!

4 个答案:

答案 0 :(得分:2)

我能想到的最接近的是

mkdir -p /mnt/tmp/
mount -o subvol=/ /dev/sdb1 /mnt/tmp/
btrfs sub create /mnt/tmp/spam/

使用[] .map对你的目的毫无意义

编辑,你也可以做这样的事情

[a, b, c, d, e].forEach(function(item) {item.doSomething()});

我使用了Array.prototype.fnName = function(methodName) { var args = Array.prototype.slice.call(arguments, 1); this.forEach(function(item) { item[methodName].apply(item, args); }); }; ,您可以将其称为fnName或其他对您有意义的内容

你会像

一样使用它
fnMap

答案 1 :(得分:1)

不假思索地回答。今天大多数浏览器都支持Array#map,而且是ES5的一部分。请参阅MDN链接:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map

[1,2,3,4,5].map(function(item){ console.log(item)}

将打印:

1
2
3
4
5

并返回undefined。如果你返回类似的东西:

[1,2,3,4,5].map(function(item){return 2*item})

它将返回:

[2,4,6,8,10]

但返回任何东西都不是必要的。你可以轻松地做一个forEach。

items.forEach(function(item){items.method()}

所有O(n)时间,因为要对数组中的n个项目应用任何内容,至少需要n次。因为循环就像它一样好。

<强> WRONG <击> ES6支持#map,但在没有设置不同设置的情况下,并非所有浏览器/ Node.j上都可用。

如果你想要一个外部库,Underscorejs有这个功能。查看他们的地图文档:http://underscorejs.org/#map

我在服务器代码中使用它,没问题。应该适用于你的游戏。如果页面加载时间有问题,您可以随时扩展Array的原型。

答案 2 :(得分:1)

Array.map()为数组中的每个项调用赋值函数。这就是匿名函数非常合适的地方:

[a, b, c].map(function (item) { item.doSomething(); });

答案 3 :(得分:0)

看到这篇文章很老,我想提供一些可以补充其他答案的元素。

让我们看一个简单的类A,它有一个方法double

class A {
  constructor(n) { this.n = n; }
  double() { return 2 * this.n; }
}

我们将要处理一系列实例。

const data = [ new A(3), new A(12), new A(4), new A(10) ];

函数包装器

Array#map()方法接受一个函数回调,它将在该数组的每个元素上执行。

从本质上讲,它归结为包装对象上的方法调用。为此,我们可以使用以下标准函数:

data.map(function(o) { return o.double() });

通常,您会遇到arrow function

data.map(o => o.double());

这减轻了对括号,花括号和return语句的需要。


解构

现在我们可以尝试改善这一点。实际上,我们可以在函数的标题中destructure objects。下面,我们直接从对象中检索double并调用它:

data.map(({ double }) => double());

但是,那是行不通的...

TypeError:thisundefined

会发生什么,我们没有在当前对象上调用double。这是因为存在函数绑定,当作为函数独立调用double时,我们未设置this的值。

我们可以将函数绑定到对象

data.map((o, _, __, fn=o.double) => fn.bind(o)())

但是...这会违背追求较短版本的目的。


Class成员箭头功能!

但是,可以使用类成员箭头功能来解决此问题。

class A {
  constructor(n) { this.n = n; }
  double = () => { return 2 * this.n; }
}

这样,我们在调用方法时就无需绑定。

那么我们就可以成功地做到:

data.map(({ double } => double());

请记住,并非所有浏览器都支持此功能。并且由于您将不得不弄乱类的声明才能使用此语法糖。我不会真的推荐它。但是,类成员箭头函数对于事件处理程序来说还是非常不错的。


演示:

class A {
  constructor(n) { this.n = n; }
  double() { return 2 * this.n; }
  triple = () => { return 3 * this.n; }
}

const data = [new A(3), new A(12), new A(4), new A(10)];

console.log(data.map(o => o.double()));

// console.log(data.map(({ double }) => double())); // won't work!

console.log(data.map((o, _,__, fn=o.double) => fn.bind(o)())); // ugly

console.log(data.map(({triple}) => triple()));