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

How to use map() to call method common to list of objects?

本文关键字:列表 常用 方法 对象 调用 何使用 map      更新时间:2023-09-26

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

假设我有这样的代码:

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

这太啰嗦了。我想把这段代码缩短成这样的

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

因为我不想使用for循环

我怎么能做到这一点与本地map函数在JS中,没有任何外部库?

提前感谢!如果这篇文章太长,我很乐意编辑它。就冲我吼吧

相关问题:

如何使用map()调用对象列表上的类方法

如何为对象列表调用相同的方法?

我没有在相关问题中使用信息,因为Python和JS使用不同的范式,我不能保证它们会工作相同。如果我错了,请不要犹豫,把我烧死在火刑柱上。

额外信息,如果你想忽略:

我已经RTFM了,措辞和例子表明我不能用map做上述操作。MDN文档将map描述为"在数组中的每个元素上调用一个提供的函数",而MSDN文档说它"在数组的每个元素上调用一个函数,并返回一个数组"。我不是试图在数组上调用方法,我试图从几个上下文对象中调用方法。如果这是不可能的,是否有天然的填充物?

我在游戏中使用这种方法,所以速度是我的主要关注点。如果有一个更理想的方式来编码这个,请让我知道!

我能想到的最接近的

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

使用[]。Map对于你的目的来说是没有意义的

编辑,你也可以这样做

Array.prototype.fnName = function(methodName) {
    var args = Array.prototype.slice.call(arguments, 1);
    this.forEach(function(item) { 
        item[methodName].apply(item, args); 
    });
};

我用的是fnName,你也可以叫它fnMap或者其他你觉得有意义的东西

你会像

那样使用它
[a,b,c].fnName('doSomething', param1, param2 ...)

不假思索地回复。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时间。For循环再好不过了

<罢工>ES6支持#map,但不是在所有浏览器/Node.js上都可用,除非设置不同的设置。

Underscorejs具有此功能,如果您确实需要外部库。查看他们的地图文档:http://underscorejs.org/#map

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

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

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

看到这篇文章很老了,我想给出一些可能补充其他答案的元素。

让我们以一个简单的类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() });

通常你会遇到一个箭头函数:

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

,它减少了对括号、花括号和return语句的需要。


Destructuring

现在我们可以试着改善这一点。实际上,我们可以在函数头文件中解构对象。下面,我们直接从对象中检索double并调用它:

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

然而,这是行不通的…

TypeError: this is undefined

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

可以将函数绑定到对象

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

但是…这将违背追求更短版本的目的。


类成员箭头函数!

但是,可以通过使用类成员箭头函数来解决这个问题。
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()));