【翻译】JavaScript中5个值得被广泛使用的数组方法

原文地址http://colintoh.com/blog/5-array-methods-that-you-should-use-today?utm_source=javascriptweekly&utm_medium=email

在2009年十月ECMAScript 5被定义正式规范以来,一些可以提高工作效率的数组方法被提出。但是,由于ES5糟糕的浏览器支持率,这些方法并未被开发者广泛使用。

“多余的”数组方法

没有人会质疑这些方法的可用性,但是如果针对它们而编写polyfill(关于polyfill,个人理解就是为了使新方法兼容各浏览器而编写的浏览器“插件”或者扩展,可以参考这篇文章)却并不值得。所以,这些新方法被认为是“good-to-have”而不是“must-have”的,或者干脆被称为“多余的”方法。Ouch!

但是前端技术发展到今天,如果你时常关注Github上一些流行的开源JS项目,你会发现这样一种趋势:开发者们越来越倾向于使用原生代码,而不依赖与第三方库。

所以,推进原生语法的广泛使用度已经非常必要了。

5个值得关注的数组方法

下面,我将介绍ES 5中的非常有用的5个数组方法,这5个方法可以提高开发者的工作效率。

1. indexOF

indexOf方法返回某个元素在数组中的索引值,如果数组中不存在此元素则返回-1

举个栗子:检查“orange”在数组中的位置

(1) 不使用indexOf()

var arr = [‘apple‘,‘orange‘,‘pear‘],
    found = false;

for(var i= 0, l = arr.length; i< l; i++){
    if(arr[i] === ‘orange‘){
        found = true;
    }
}

console.log("found:",found);

(2) 使用indexOf()

var arr = [‘apple‘,‘orange‘,‘pear‘];

console.log("found:", arr.indexOf("orange") != -1);

代码简洁了很多吧!

现在我有了新的需求:我想知道数组中所有符合给定条件的元素。怎么办?

2. filter

filter()方法创建一个指定数组中符合给定条件的所有元素组成的新数组

举个栗子:找出数组中name为“orange”的所有元素

(1) 不用filter()

var arr = [
    {"name":"apple", "count": 2},
    {"name":"orange", "count": 5},
    {"name":"pear", "count": 3},
    {"name":"orange", "count": 16},
];

var newArr = [];

for(var i= 0, l = arr.length; i< l; i++){
    if(arr[i].name === "orange" ){
        newArr.push(arr[i]);
    }
}

console.log("Filter results:",newArr);

(2) 使用filter()

var arr = [
    {"name":"apple", "count": 2},
    {"name":"orange", "count": 5},
    {"name":"pear", "count": 3},
    {"name":"orange", "count": 16},
];

var newArr = arr.filter(function(item){
    return item.name === "orange";
});

console.log("Filter results:",newArr);

代码简洁了很多。

3. foreach()

foreach()方法为数组中的每个元素执行一次给定的方法

举个栗子:for循环和foreach()方法对比

function test(){
    var arr = [1,2,3,4,5,6,7,8];

    // Uses the usual "for" loop to iterate
    for(var i= 0, l = arr.length; i< l; i++){
        console.log(arr[i]);
    }

    console.log("========================");

    //Uses forEach to iterate
    arr.forEach(function(item,index){
        console.log(item);
    });
}

foreach()方法是for循环的一种升级写法。本人建议如果可以选择,应该尽量使用foreach()方法。

使用for循环时存在一个容易被忽视的问题:在for循环中声明的变量(比如上例中的var i=0)并不是for循环中的局部变量,而是for循环所在作用域内的局部变量。上例中,在for循环中声明的变量 var i = 0 实际上是方法test()作用域内的局部变量,i非常容易被test()作用域内的其他逻辑访问和重写,从而造成一些问题。

实际上,通过jsperf的测试表明,for循环的性能比foreach()要好很多。

但是,我个人始终认为,除非是处理百万级以上的大数据,否则仍然坚持使用foreach()方法。节省毫秒级的时间并不作为提升产品性能的主要考虑因素。

4. map()

 对数组的每个元素调用定义的回调函数并返回包含结果的数组

举个栗子:解析一个数组,为数组中每个元素新增一个fullname属性,并返回新数组

(1) 不使用map()

var oldArr = [{first_name:"Colin",last_name:"Toh"},{first_name:"Addy",last_name:"Osmani"},{first_name:"Yehuda",last_name:"Katz"}];

function getNewArr(){

    var newArr = [];

    for(var i= 0, l = oldArr.length; i< l; i++){
        var item = oldArr[i];
        item.full_name = [item.first_name,item.last_name].join(" ");
        newArr[i] = item;
    }

    return newArr;
}

console.log(getNewArr());

(2) 使用map()

var oldArr = [{first_name:"Colin",last_name:"Toh"},{first_name:"Addy",last_name:"Osmani"},{first_name:"Yehuda",last_name:"Katz"}];

function getNewArr(){

    return oldArr.map(function(item,index){
        item.full_name = [item.first_name,item.last_name].join(" ");
        return item;
    });

}

console.log(getNewArr());

map()方法在处理包含服务器数据交互操作的重型JavaScript应用中非常适用。

5. reduce()

 对数组中的所有元素调用指定的回调函数。 该回调函数的返回值为累积结果,并且此返回值在下一次调用该回调函数时作为参数提供

老实说,在使用reduce()之前我斟酌了很久。reduce()的概念对我来说非常抽象,尤其是“累积”这个词。直到在nodeschool中开始学习一系列的JavaScript方法之后才逐渐掌握reduce()的概念。但是我仍没有发现它有多大作用,直到有一天我在重构自己代码的时候才发现,reduce()简直吊炸天!

举个栗子:解析一个数组,并且返回一个包含每个元素在数组中出现次数的对象

(1) 不用reduce()

var arr = ["apple","orange","apple","orange","pear","orange"];

function getWordCnt(){
    var obj = {};

    for(var i= 0, l = arr.length; i< l; i++){
        var item = arr[i];
        obj[item] = (obj[item] +1 ) || 1;
    }

    return obj;
}

console.log(getWordCnt());

(2)使用reduce()

var arr = ["apple","orange","apple","orange","pear","orange"];

function getWordCnt(){
    return arr.reduce(function(prev,next){
        prev[next] = (prev[next] + 1) || 1;
        return prev;
    },{});
}

console.log(getWordCnt());

下面我将解释一下对于reduce()的个人理解。

reduce(callback,initialValue) 有两个参数,callback函数和initialValue。其中callback函数包含4个参数:prev,next,index和array。我们一般只需要用到prev和next两个参数。

prev参数代表数组中的第一个元素,next代表数组中的第二个元素。注意:如果initialValue参数被设置,prev则代表initialValue,而next代表数组中的第一个元素。比如上例中。initialValue被设置为空白对象{},则prev为{}。

/*
* Difference between not passing any parameters
* and passing in a additional parameter into `reduce()`
*/

var arr = ["apple","orange"];

function noPassValue(){
    return arr.reduce(function(prev,next){
        console.log("prev:",prev);
        console.log("next:",next);

        return prev + " " +next;
    });
}
function passValue(){
    return arr.reduce(function(prev,next){
        console.log("prev:",prev);
        console.log("next:",next);

        prev[next] = 1;
        return prev;
    },{});
}

console.log("No Additional parameter:",noPassValue());
console.log("----------------");
console.log("With {} as an additional parameter:",passValue());

上面的代码中,每次迭代都返回一个值,这个值被当做下一次迭代的prev参数传入。

下面的代码会更加清晰的显示reduce()的功能:

var arr = ["apple","orange","apple","pear"];

function getWordCnt(){
    return arr.reduce(function(prev,next,index){
        console.log("<b>Iteration "+index+"</b>");
        console.log("prev:",prev);
        console.log("next:",next);

        prev[next] = ++prev[next] || 1;
        console.log("Passing this to the ‘prev‘ of the next iteration if any:",prev);
        console.log("---------------");
        return prev;
    },{});
}

console.log("<b>Final Object:</b>",getWordCnt());

Demethodizing

以上提到的这些方法虽然是只针对数组的,但是同时可以被节点列表、Jquery对象甚至字符串使用。我们可以通过一种“demethodizing”的技术来扩展这些数组方法。

// Demethodizing the Array method, forEach(),  into a generic "each"
var each = Function.prototype.call.bind([].forEach);

var nodeList = document.querySelectorAll("p");

each(nodeList,bold);

function bold(node){
   node.style.fontWeight ="bold";
}

我们通过 Function.prototype.call.bind 将foreach方法扩展为function类的each方法,现在each方法可以被数组以外的对象使用了。

浏览器支持度

根据ECMAScript 5 compatibility table,以上5个方法可以再所有的手机浏览器和几乎所有桌面浏览器中使用(当我说“所有”的时候,IE9以下的浏览器请自觉离开)。

时间: 2024-10-27 00:33:11

【翻译】JavaScript中5个值得被广泛使用的数组方法的相关文章

Javascript中两种最通用的定义类的方法

在Javascript中,一切都是对象,包括函数.在Javascript中并没有真正的类,不能像C#,PHP等语言中用 class xxx来定义.但Javascript中提供了一种折中的方案:把对象定义描述为对象的配方(先看一下例子会比较容易理解).定义类的方法有很多种,这里有两中较为通用的方法,大家参考一下.这两种方法均可以解决 构造函数会重复生成函数,为每个对象都创建独立版本的函数的问题.解决了重复初始化函数和函数共享的问题??提示音:http://www.huiyi8.com/tishiy

JavaScript 中关于Date的内置对象属性和方法的总结

Date 属性: 1.constructor    所建立对象的函数参考 2.prototype      能够为对象加入的属性和方法 方法: 1.getDay()    返回一周中的第几天(0-6) 2.getYear()    返回年份.2000年以前为2位,2000(包含)以后为4位 3.getFullYear()     返回完整的4位年份数 4.getMonth()      返回月份数(0-11) 5.getDate()       返回日(1-31) 6.getHours()  

JavaScript中的call()和apply()方法,借此实现继承

1.方法定义 call方法: 语法:call([thisObj[,arg1[, arg2[,   [,.argN]]]]]) 定义:调用一个对象的一个方法,以另一个对象替换当前对象. 说明: call 方法可以用来代替另一个对象调用一个方法.call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象. 如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj. apply方法: 语法:apply([thisObj[,argArray]])

javascript中的startWith和endWith的几种实现方法

JavaScript采用正则表达式实现startWith.endWith效果函数 代码如下: String.prototype.startWith=function(str){       var reg=new RegExp("^"+str);       return reg.test(this);        } String.prototype.endWith=function(str){       var reg=new RegExp(str+"$")

201504251733_《JavaScript中判断是否为一个数字所写的一个方法》

var isNumber=function isNumber(value){ return typeof value==='number'&&isFinite(value); }

Arcgis Javascript中geometryEngine报错’hq‘of undefined的解决方法

这个问题困扰了我一个星期,原因是使用geomagicbuffer时候,有的线可正常使用,有的就直接报错,一直没有解决,后来发现是api自己的bug导致的 干脆直接读代码,在geometryEngine第737行,有这么一句话(不同版本的额api可能会不同): if((this.Ec||1E4<u.jq&&1<u.Ci.length)......... 报错的就是这里,因为u没有判断是否存在,导致执行u.jq时候报错 按照下面修改就好啦 if((u)&&(u.jq

每个JavaScript程序员都需要知道的5个数组方法

Array.forEach() .forEach() 方法能够方便的让你 遍历数组里的每个元素,你可以在回调函数里对每个元素进行操作..forEach()方法没有返回值,你不需要在回调函数里写return,这是无意义的. var animals = ['dog', 'cat', 'mouse']; animals.forEach(function(item){ console.log(item); }); Array.map() .map() 方法能够遍历整个数组,然后 返回一个新数组,这个新数

JavaScript中的工厂方法、构造函数与class

JavaScript中的工厂方法.构造函数与class 本文转载自:众成翻译 译者:谢于中 链接:http://www.zcfy.cc/article/1129 原文:https://medium.com/javascript-scene/javascript-factory-functions-vs-constructor-functions-vs-classes-2f22ceddf33e#.wby148xu6 在ES6出现之前,人们常常疑惑JavaScript中的工厂模式和构造函数模式到底有

【转】深入浅出 JavaScript 中的 this

Java 等面向对象的语言中,this 关键字的含义是明确且具体的,即指代当前对象.一般在编译期确定下来,或称为编译期绑定.而在 JavaScript 中,this 是动态绑定,或称为运行期绑定的,这就导致 JavaScript 中的 this 关键字有能力具备多重含义,带来灵活性的同时,也为初学者带来不少困惑.本文仅就这一问题展开讨论,阅罢本文,读者若能正确回答 JavaScript 中的 What ’s this 问题,作为作者,我就会觉得花费这么多功夫,撰写这样一篇文章是值得的. Java