javascript forEach 方法有什么用(那个地图做不到)?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3034392/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 03:00:52  来源:igfitidea点击:

what use does the javascript forEach method have (that map can't do)?

javascriptarraysdictionaryforeachprototype

提问by JohnMerlino

The only difference I see in map and foreach is that mapis returning an array and forEachis not. However, I don't even understand the last line of the forEachmethod "func.call(scope, this[i], i, this);". For example, isn't "this" and "scope" referring to same object and isn't this[i]and ireferring to the current value in the loop?

我在 map 和 foreach 中看到的唯一区别map是返回一个数组而forEach不是。但是,我什至不明白forEach方法“ func.call(scope, this[i], i, this);”的最后一行。例如,不为“ this”和“ scope”,指的同一个对象,而不是this[i]i参照在环路中的电流值?

I noticed on another post someone said "Use forEachwhen you want to do something on the basis of each element of the list. You might be adding things to the page, for example. Essentially, it's great for when you want "side effects". I don't know what is meant by side effects.

我在另一篇文章中注意到有人说“forEach当你想根据列表的每个元素做某事时使用。例如,你可能正在向页面添加内容。本质上,当你想要“副作用”时,它非常有用。我不知道副作用是什么意思。

Array.prototype.map = function(fnc) {
    var a = new Array(this.length);
    for (var i = 0; i < this.length; i++) {
        a[i] = fnc(this[i]);
    }
    return a;
}

Array.prototype.forEach = function(func, scope) { 
    scope = scope || this; 
    for (var i = 0, l = this.length; i < l; i++) {
        func.call(scope, this[i], i, this); 
    } 
}

Finally, are there any real uses for these methods in javascript (since we aren't updating a database) other than to manipulate numbers like this:

最后,除了像这样操作数字之外,这些方法在 javascript 中是否有任何实际用途(因为我们没有更新数据库):

alert([1,2,3,4].map(function(x){ return x + 1})); //this is the only example I ever see of map in javascript.

Thanks for any reply.

感谢您的任何答复。

回答by Ken Redler

The essential difference between mapand forEachin your example is that forEachoperates on the original array elements, whereas mapexplicitly returns a new array as a result.

您的示例中map和之间的本质区别在于对原始数组元素进行操作,而结果显式返回一个新数组。forEachforEachmap

With forEachyou are taking some action with -- and optionally changing -- each element in the original array. The forEachmethod runs the function you provide for each element, but returns nothing (undefined). On the other hand, mapwalks through the array, applies a function to each element, and emits the result as a new array.

随着forEach您对原始数组中的每个元素进行一些操作,并且可以选择更改。该forEach方法运行您为每个元素提供的函数,但不返回任何内容 ( undefined)。另一方面,map遍历数组,将函数应用于每个元素,并将结果作为新数组发出

The "side effect" with forEachis that the original array is being changed. "No side effect" with mapmeans that, in idiomatic usage, the original array elements are notchanged; the new array is a one-to-one mapping of each element in the original array -- the mapping transform being your provided function.

“副作用”forEach是原始数组正在被更改。“没有副作用”与map,在习惯用法,原始数组元素手段改变; 新数组是原始数组中每个元素的一对一映射——映射转换是您提供的函数。

The fact that there's no database involved does not mean that you won't have to operate on data structures, which, after all, is one of the essences of programming in any language. As for your last question, your array can contain not only numbers, but objects, strings, functions, etc.

不涉及数据库这一事实并不意味着您不必对数据结构进行操作,毕竟这是任何语言编程的本质之一。至于你的最后一个问题,你的数组不仅可以包含数字,还可以包含对象、字符串、函数等。

回答by nrabinowitz

The main difference between the two methods is conceptual and stylistic: You use forEachwhen you want to do something toor witheach element of an array (doing "with" is what the post you cite meant by "side-effects", I think), whereas you use mapwhen you want to copy and transformeach element of an array (without changing the original).

这两种方法之间的主要区别是概念和风格:您可以使用forEach,当你想要做的事,以数组中的每个元素(做“和”什么是你引用的“副作用”的意思后,我想) ,而map当您想要复制和转换数组的每个元素(不更改原始元素)时使用。

Because both mapand forEachcall a function on each item in an array, and that function is user-defined, there is almost nothing you can do with one and not with the other. It's possible, though ugly, to use mapto modify an array in-place and/or do something with array elements:

因为mapforEach对数组中的每一项都调用一个函数,而且该函数是用户定义的,所以您几乎无法对其中一个进行任何操作,而对另一个则无能为力。尽管很难看,但可以使用map就地修改数组和/或对数组元素执行某些操作:

var a = [{ val: 1 }, { val: 2 }, { val: 3 }];
a.map(function(el) {
    el.val++; // modify element in-place
    alert(el.val); // do something with each element
});
// a now contains [{ val: 2 }, { val: 3 }, { val: 4 }]

but much cleaner and more obvious as to your intent to use forEach:

但就您的使用意图而言,更清晰、更明显forEach

var a = [{ val: 1 }, { val: 2 }, { val: 3 }];
a.forEach(function(el) { 
    el.val++;
    alert(el.val);
});

Especially if, as is usually the case in the real world, elis a usefully human-readable variable:

特别是如果,就像现实世界中通常的情况,el是一个有用的人类可读的变量:

cats.forEach(function(cat) { 
    cat.meow(); // nicer than cats[x].meow()
});

In the same way, you can easily use forEachto make a new array:

同样的方法,你可以很容易地使用forEach来创建一个新的数组:

var a = [1,2,3],
    b = [];
a.forEach(function(el) { 
    b.push(el+1); 
});
// b is now [2,3,4], a is unchanged

but it's cleaner to use map:

但使用起来更干净map

var a = [1,2,3],
    b = a.map(function(el) { 
        return el+1; 
    });

Note as well that, because mapmakes a new array, it likely incurs at least some performance/memory hit when all you need is iteration, particularly for large arrays - see http://jsperf.com/map-foreach

还要注意的是,因为map创建了一个新数组,所以当您只需要迭代时,它可能至少会导致一些性能/内存损失,特别是对于大型数组 - 请参见http://jsperf.com/map-foreach

As for why you'd want to use these functions, they're helpful any time you need to do array manipulation in javascript, which (even if we're just talking about javascript in a browser environment) is pretty often, almost any time you're accessing an array that you're not writing down by hand in your code. You might be dealing with an array of DOM elements on the page, or data pulled from an AJAX request, or data entered in a form by the user. One common example I run into is pulling data from an external API, where you might want to use mapto transform the data into the format you want and then use forEachto iterate over your new array in order to display it to your user.

至于您为什么要使用这些函数,它们在您需要在 javascript 中进行数组操作的任何时候都会很有帮助,这(即使我们只是在浏览器环境中讨论 javascript)也很常见,几乎任何时候您正在访问一个不是在代码中手写的数组。您可能正在处理页面上的一组 DOM 元素,或者从 AJAX 请求中提取的数据,或者用户在表单中输入的数据。我遇到的一个常见示例是从外部 API 中提取数据,您可能希望使用该 APImap将数据转换为您想要的格式,然后用于forEach迭代新数组以将其显示给您的用户。

回答by Hyman Tang

The voted answer (from Ken Redler) is misleading.

投票的答案(来自 Ken Redler)具有误导性。

A side effectin computer science means that a property of a function/method alters a global state [wiki]. In some narrow sense, this may also include reading from a global state, rather than from arguments. In imperative or OO programing, side effects appear most of the time. And you are probably making use of it without realizing.

副作用在计算机科学装置,其的功能/方法涂改一个全局状态的性质[维基]。在某些狭义上,这也可能包括从全局状态中读取,而不是从参数中读取。在命令式或面向对象编程中,大多数时候都会出现副作用。你可能在不知不觉中使用它。

The significiant difference between forEachand mapis that mapallocates memory and stores the returning value, while forEachthrows it away. See emca specfor more information.

forEach和之间的显着区别mapmap分配内存并存储返回值,而forEach将其丢弃。有关详细信息,请参阅emca 规范

As for the reason why people say forEachis used when you want a side effect is that the return value of forEachis always undefined. If it has no side effect (does not change global state), then the function is just wasting cpu time. An optimizing compiler will eliminate this code block and replace the it with the final value (undefined).

至于为什么人们说forEachis used when you want a side effect 的原因是 的返回值forEach总是undefined。如果它没有副作用(不改变全局状态),那么该函数只是在浪费 CPU 时间。优化编译器将消除此代码块并将其替换为最终值 ( undefined)。

By the way, it should be noted that JavaScript has no restriction on side effects. You can still modify the original array inside map.

顺便说一下,需要注意的是,JavaScript 对副作用没有限制。你仍然可以修改里面的原始数组map

var a = [1,2,3]; //original
var b = a.map( function(x,i){a[i] = 2*x; return x+1} );
console.log("modified=%j\nnew array=%j",a,b);
// output:
// modified=[2,4,6]
// new array=[2,3,4]

回答by Sumukh Barve

This is a beautiful question with an unexpected answer.

这是一个美丽的问题,有一个意想不到的答案。

The following is based on the official description of Array.prototype.map().

以下内容以官方说明为准Array.prototype.map()

There is nothingthat forEach()can do that map()cannot. That is, map()is a strict super-setof forEach().

没有什么forEach()可以做到这一点map()做不到。也就是说,map()是一个严格的超集forEach()

Although map()is usually used to create a new array, it may alsobe used to change the current array. The following example illustrates this:

虽然map()通常用于创建新数组,但可能用于更改当前数组。以下示例说明了这一点:

var a = [0, 1, 2, 3, 4], mapped = null;
mapped = a.map(function (x) { a[x] = x*x*x; return x*x; });
console.log(mapped); // logs [0, 1, 4, 9, 16]  As expected, these are squares.
console.log(a); // logs [0, 1, 8, 27, 64] These are cubes of the original array!!

In the above example, awas conveniently set such that a[i] === ifor i < a.length. Even so, it demonstrates the power of map(), and in particular its ability to change the array on which it is called.

在上面的例子中,a被方便地设置a[i] === i为 for i < a.length。即便如此,它还是展示了 的强大功能map(),特别是它改变调用它的数组的能力。

Note1:
The official description implies that map()may even change lengththe array on which it is called! However, I cannot see (a good) reason to do this.

注1:
官方描述暗示map()甚至可能改变调用它的数组的长度!但是,我看不到(一个很好的)这样做的理由。

Note2:
While map()map is a super-set of forEach(), forEach()should still be used where one desires the change a given array. This makes your intentions clear.

注意 2:
虽然map()map 是 的超集forEach()forEach()但仍应在需要更改给定数组的地方使用。这使您的意图明确。

Hope this helped.

希望这有帮助。

回答by wombleton

You can use mapas though it were forEach.

您可以map像使用forEach.

It will do more than it has to, however.

然而,它会做的比它必须做的更多。

scopecan be an arbitrary object; it's by no means necessarily this.

scope可以是任意对象;这绝不是必然的this

As for whether there are real uses for mapand forEach, as well to ask if there are real uses for foror whileloops.

至于mapand是否有真正的用途forEach,还要问一下 forforwhile循环是否有真正的用途。

回答by maschwenk

While all the previous questions are correct, I would definitely make a different distinction. The use of mapand forEachcan imply intent.

虽然之前的所有问题都是正确的,但我肯定会做出不同的区分。使用mapforEach可以暗示意图。

I like to use mapwhen I am simply transforming the existing data in some way (but want to make sure the original data is unchanged.

map当我只是以某种方式转换现有数据时,我喜欢使用它(但要确保原始数据不变。

I like to use forEachwhen I am modifying the collection in place.

我喜欢forEach在适当地修改集合时使用。

For instance,

例如,

var b = [{ val: 1 }, { val: 2 }, { val: 3 }];
var c = b.map(function(el) {
    return { val: el.val + 1 }; // modify element in-place
});
console.log(b);
//  [{ val: 1 }, { val: 2 }, { val: 3 }]
console.log(c);
//  [{ val: 3 }, { val: 4 }, { val: 5 }]

My rule of thumb being making sure when you mapyou are always creating some new object/value to return for each element of the source list and returningit rather than just performing some operation on each element.

我的经验法则是确保何时map总是创建一些新对象/值来为源列表的每个元素返回返回它,而不是仅仅对每个元素执行一些操作。

Unless you have any real need to modify the existing list, it doesn't really make sense to modify it in place, and fits better into functional/immutable programming styles.

除非您确实需要修改现有列表,否则就地修改它没有任何意义,并且更适合函数式/不可变编程风格。

回答by charsi

TL;DR answer --

TL; DR 回答——

map always returns another array.

map 总是返回另一个数组。

forEach does not. It is up to you to decide what it does. Return an array if you want or do something else if you don't.

forEach 没有。由您来决定它的作用。如果需要,请返回一个数组,如果不需要,请执行其他操作。

Flexibility is desirable is certain situations. If it isn't for what you are dealing with then use map.

在某些情况下,灵活性是可取的。如果不是您要处理的内容,请使用 map。

回答by Markku Uttula

Once again, I feel like a necromancer adding a response to a question that has been asked 5 years ago (happily there is rather recent activity, so I am not the only one disturbing the dead:).

再一次,我感觉自己像个死灵法师,对 5 年前提出的问题进行了回答(幸好最近有活动,所以我不是唯一一个打扰死者的人:)。

Others have already posted about your main question regarding the difference between the functions. But for...

其他人已经发布了有关功能之间差异的主要问题。但对于...

are there any real uses for these methods in javascript (since we aren't updating a database) other than to manipulate numbers like this:

除了像这样操作数字之外,这些方法在 javascript 中是否有任何实际用途(因为我们没有更新数据库):

...it's funny you should ask. Just today I wrote a piece of code that assigns a number of values from a regular expression to multiple variables using map for transformation. It was used to convert a very complicated text based structure into visualizeable data ... but for simplicity's sake, I shall offer an example using date strings, because those are probably more familiar for everyone (though, if my problem had actually been with dates, instead of map I would've used Date-object, which would've done the job splendidly on its own).

......你应该问这很有趣。就在今天,我写了一段代码,使用 map 将正则表达式中的多个值分配给多个变量进行转换。它被用来将非常复杂的基于文本的结构转换为可视化数据......但为了简单起见,我将提供一个使用日期字符串的示例,因为每个人可能更熟悉这些(不过,如果我的问题实际上是日期,而不是我会使用日期对象的地图,它会自己出色地完成工作)。

const DATE_REGEXP = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})\.(\d{3})Z$/;
const TEST_STRING = '2016-01-04T03:20:00.000Z';

var [
    iYear,
    iMonth,
    iDay,
    iHour,
    iMinute,
    iSecond,
    iMillisecond
    ] = DATE_REGEXP
        // We take our regular expression and...
        .exec(TEST_STRING)
        // ...execute it against our string (resulting in an array of matches)...
        .slice(1)
        // ...drop the 0th element from those (which is the "full string match")...
        .map(value => parseInt(value, 10));
        // ...and map the rest of the values to integers...

// ...which we now have as individual variables at our perusal
console.debug('RESULT =>', iYear, iMonth, iDay, iHour, iMinute, iSecond, iMillisecond);

So ... while this was just an example - and only did a very basic transformation for the data (just for sake of example) ... having done this without map would've been a much more tedious task.

所以......虽然这只是一个例子 - 并且只对数据进行了非常基本的转换(只是为了示例)......在没有地图的情况下完成这项工作将是一项更加乏味的任务。

Granted, it is written in a version of JavaScript that I don't think too many browsers support yet(at least fully) but - we're getting there. If I needed to run it in browser, I believe it would transpile nicely.

当然,它是用 JavaScript 版本编写的,我认为目前还没有太多浏览器支持(至少完全支持),但是 - 我们正在实现。如果我需要在浏览器中运行它,我相信它会很好地转换。