JavaScript中的filter和map区别问题

38

在我解决了数组对象最小值/最大值问题的基础上,我在思考使用filter和map方法的性能比较。

于是我在我的代码中针对这一点进行了测试,并准备在FireBug中查看结果。

以下是我的测试代码:

var _vec = this.vec;
min_x = Math.min.apply(Math, _vec.filter(function(el){ return el["x"]; }));
min_y = Math.min.apply(Math, _vec.map(function(el){ return el["x"]; }));
map方法的返回结果正确,但是filter方法的返回结果却是NaN。我将代码进行了调试和分步执行并最终检查了结果,看起来内部函数返回的是_vecx属性,而实际从filter方法返回的数组却是未经过滤的_vec数组。
我相信我对filter的使用是正确的,有其他人能看出我的问题吗?
这里有一个简单的测试:
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>S:GTC Map Test</title>
</head>
<body>
<script type="text/javascript">
function vector(x,y,z) { this.x = x; this.y =y; this.z=z; }
var vec = [];
vec.push(new vector(1,1,1));
vec.push(new vector(2,2,2));
vec.push(new vector(2,3,3));
var _vec = vec;
min_x = Math.min.apply(Math, _vec.filter(function(el){ return el["x"]; }));
min_y = Math.min.apply(Math, _vec.map(function(el){ return el["x"]; }));

document.write("<br>filter = " + min_x);
document.write("<br>map = " + min_y);
</script>
</body>
</html>
3个回答

86

不,filter方法不会返回未筛选的数组。它返回一个包含内部函数返回值为true的元素的数组。

由于您未从内部函数返回布尔值,所以该值被转换为布尔值,因此对象引用被转换为true。因此,它返回一个包含原始数组中所有项的新数组。

filter方法与map方法不同。 map方法用于转换数组的每个元素,而filter方法用于选择数组的某些元素。将这两种方法进行性能比较是没有意义的,因为它们仅有其中一个可以做你想做的事情。


3
啊。看来我误解了过滤函数的工作方式。我以为它会将修改后的对象返回到数组中。 - graham.reeds
5
不,map和filter都会返回新的数组。 - omkar

42

摘自:

JavaScript权威指南
作者:David Flanagan

map()

The map() method passes each element of the array on which it is invoked to the function you specify, and returns an array containing the values returned by that function.

For example:

a = [1, 2, 3];

b = a.map(function(x) { return x*x; });  // b is [1, 4, 9]

The function you pass to map() is invoked in the same way as a function passed to forEach(). For the map() method, however, the function you pass should return a value.Note that map() returns a new array: it does not modify the array it is invoked on. If that array is sparse, the returned array will be sparse in the same way: it will have the same length and the same missing elements.

filter()

The method returns an array containing a subset of the elements of the array on which it is invoked. The function you pass to it should be predicate: a function that returns true or false. The predicate is invoked just as for forEach() and map(). If the return value is true , or a value that converts to true, then the element passed to the predicate is a member of the subset and is added to the array that will become the return value.

Examples:

a = [5, 4, 3, 2, 1];

smallvalues = a.filter(function(x) { return x < 3 });   // [2, 1]

everyother = a.filter(function(x,i) { return i%2==0 }); // [5, 3, 1]

变量 everyother 起初让我产生了误解,它将 a 传递给 x,而 i 是我们可以在 map 中添加和使用的数组索引,因此 everyother 的 filter 方法不处理数组 a 中的值,而是处理索引 i。 - Bashar Abu Shamaa

5
// MAP creates a new array
// MPA return new Array
var arr = [1, 2, 3, 4, 5, 6, 7];

var newArr = arr.map((el) => {
  return el * 2;
});

console.log(newArr); //2,4,3,8,10,12,14

// filter() return new Array
var newFilter = arr.filter((el) => {
   return el * 2;
});
console.log(newFilter); // 1,2,3,4,5,6,7

现在你可以看到,我在 mapfilter 中都使用了 return el*2,它们的输出结果是不同的。

filter() filter() 方法创建一个新数组,其中包含通过函数实现的测试条件的所有数组元素。

如果条件返回 true,则元素被推入输出数组。如果条件返回 false,则元素不被推入输出数组。

var arr = [1, 2, 3, 4, 5, 6, 7];
var newFilter = arr.filter((el) => {
  return el > 3;
});
console.log(newFilter);  //[1, 2, 3, 4]

Map() map()方法用于从现有数组中创建新数组,将函数应用于第一个数组的每个元素。 var arr = [1, 2, 3, 4, 5, 6, 7];

var newArr = arr.map((el) => {
  return el * 2;
});

console.log(newArr); //2,4,3,8,10,12,14

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接