ES5新特性:理解 Array 中增强的 9 个 API

为了更方便的对JS中Array进行操作,ES5规范在Array的原型上新增了9个方法,分别是forEach、filter、map、reduce、reduceRight、some、every、indexOf 和 lastIndexOf,本文将对这几个方法进行详细的讲解,并对每一个方法进行原型扩展,以兼容不支持ES5的浏览器。

forEach(callback[,thisArg])



在ES5之前,我们可以通过for和for in 两种方式来遍历数组,而ES5引入了一个新方法forEach,使数组遍历更加简洁,forEach需要传递2个参数,第一个参数是回调函数,是必选参数,第二个参数是一个对象,用来改变callback中的this指向,是可选参数。

var arr = [‘a‘,‘b‘,‘c‘];
arr.forEach(function(v,i,r){
    console.log(v,i,r);
})
->
a 0 ["a", "b", "c"]
b 1 ["a", "b", "c"]
c 2 ["a", "b", "c"]

从输出的结果可以看出,callback中传入了3个参数v,i,r 分别表示当前元素、当前位置、数组对象。再看看使用 thisArg 的例子:

var obj = {
   print:function(a,b){
       console.log(a,b);
   }
};
var arr = [‘a‘,‘b‘,‘c‘];
arr.forEach(function(v,i,a){
   this.print(v,i);
},obj);

不传thisArgs时,callback中的 this 默认指向 window 对象,当传递thisArg时,callback中的this就指向了thisArg,因此这个参数的目的就是为了改变回调函数中的this指向。

对于不支持ES5的浏览器,我们可以对forEach进行简单的扩展来兼容老的浏览器:

if(!Array.prototype.forEach){
    Array.prototype.forEach = function(callback,thisArg){
        for (var i=0;i<this.length;i++){
            //当thisArg为undefined时,JS引擎会将window作为其调用者
            callback.call(thisArg,this[i],i,this.toString());
        }
    }
}

filter(callback[,thisArg])



filter是`过滤`的意思,所以这个方法的作用就是返回一个匹配过滤条件的新数组,其接收两个参数callback和thisArg, callback也是回调函数,主要用于对元素进行条件匹配,thisArg和forEach中的thisArg作用一样,在这里就不重复了,看下面示例:

var arr = ["a","b","a","c"];
var newArr = arr.filter(function(item){
     return item === "a";
});

newArr -> ["a","a"]

代码很简单,一看就明白,没有filter的时候,要实现这个功能,我们事先要创建一个空的数组,把匹配到的元素再push进去,现在就不需要那么麻烦了,我们再看看对filter的扩展:

if(!Array.prototype.filter) {
    Array.prototype.filter = function (callback, thisArg) {
        var temp = [];
        for (var i = 0; i < this.length; i++) {
           if(callback.call(thisArg,this[i])){
               //如果callback返回true,则该元素符合过滤条件,将元素压入temp中
               temp.push(this[i]);
           }
        }
        return temp;
    }
}

map(callback[,thisArg])



map的作用是对原数组进行加工处理后并将其作为一个新数组返回,该方法同样接收两个参数,callback是回调函数用于对数组进行加工处理,thisArg和上面的一样。先看一个简单的例子:

var arr = [
   {w:10,h:10}, //定义长和宽
   {w:15,h:20},
   {w:12,h:12}
];
var newArr = arr.map(function(item){
   //根据长宽计算出面积并赋值给新属性area
   item.area = item.w * item.h;
   return item;
});
newArr[0] - > {w: 10, h: 10, area: 100}

可以看出,newArr返回的是增加了area属性的对象数组。这个方法非常实用,一般情况下,当一个ajax请求返回时,我们都要对其结果集进行过滤和校验等操作,这时map就派上用场了。我们再看看如果对map进行兼容性扩展:

if(!Array.prototype.map) {
   Array.prototype.map = function (callback, thisArg) {
       var temp = [];
       for (var i = 0; i < this.length; i++) {
           var newItem = callback.call(thisArg,this[i]);
           temp.push(newItem); //将callback返回的新元素压入temp中
       }
       return temp;
   }
}

reduce (callback[,initialValue])



reduce在这里有`减少`的意思,那reduce到底是干什么用的呢?看看比较官方的解释:The method applies function against an accumulator and each value of the array (from left-to-right) to reduce it to single value. 自己慢慢体会吧,我们先看看怎么使用吧,用的多了自然就明白了:

var arr = [1,2,3,4];
var newArr = arr.reduce(function(previousValue, currentValue, currentIndex, array){
    console.log(previousValue, currentValue,currentIndex);
    return previousValue + currentValue;
});

1 2 1
3 3 2
6 4 3

newArr -> 10

从运行结果可以看出,reduce实现了数组元素的累加功能,reduce接收4个参数,previousValue存放的是上一次callback返回的结果,currentValue是当前元素,currentIndex是当前元素位置,array是当前数组。previousValue 初始值为数组的第一个元素,数组从第2个元素开始遍历。我们再来看看initialValue 究竟是什么鬼:

var arr = [1,2,3,4];
var newArr = arr.reduce(function(previousValue, currentValue, currentIndex, array){
    console.log(previousValue, currentValue,currentIndex);
    return previousValue + currentValue;
},100);

100 1 0
101 2 1
103 3 2
106 4 3

newArr -> 110

从运行结果看,initialValue参数指定了previousValue的初始值,更重要的是,这次数组是从第1个位置开始遍历,而不再是从第2个位置开始了。 现在回过头来,对照这两个例子,我相信你一定能够理解reduce的作用了。下面对于reduce的扩展会巩固你对reduce的理解:

if(!Array.prototype.reduce) {
   Array.prototype.reduce = function (callback, initialValue) {
        var previousValue = initialValue || this[0];//如果不指定intialValue,则默认为数组的第一个元素
        //如果不指定initialValue,i从1开始遍历,否则就从0开始遍历
        for (var i = initialValue?0:1; i < this.length; i++) {
            //previousValue 累加每一次返回的结果
            previousValue = callback(previousValue, this[i],i,this.toString());
        }
        return previousValue;
    }
}

reduceRight (callback[,initialValue])



和reduce的作用完全相同,唯一的不同是,reduceRight是从右至左遍历数组的元素。

some (callback[,thisArg])



some是`某些、一些`的意思,因此,some的作用是检测数组中的每一个元素,当callback返回true时就停止遍历,并返回true,这样的描述似乎有些抽象,看代码,一切尽在代码中:

var arr = [ 1, 2, 3, 4];
var result = arr.some( function( item, index, array ){
    console.log( item, index, array);
    return item > 2;
});
->
 1 0 [1, 2, 3, 4]
 2 1 [1, 2, 3, 4]
 3 2 [1, 2, 3, 4]

 restule -> true

从运行结果看,some检测整个数组,只要当arr中有一个元素符合条件item>2 就停止检测和遍历,并返回true,以表示检测到目标。这和我们在for循环中使用break语言的作用有点类似,这会儿你应该明白some的作用了吧! 下面对于some的扩展会有助于你对some的理解:

if(!Array.prototype.some) {
   Array.prototype.some = function (callback, thisArg) {
        for (var i = 0; i < this.length; i++) {
           if(callback.call(thisArg,this[i],i,this.toString())){

               return true; //检测到callback返回true,跳出循环,并返回true
           }
        }
        return false; //一个符合条件的都没有检测到,返回false
    }
}

every (callback[,thisArg])



every是`每一个`的意思,相比some来讲,every对元素的检测更加严格,那every到底是干什么的呢,看代码就知道了:

var arr = [ 1, 2, 3, 4];
var result = arr.every( function( item, index, array ){
    console.log( item, index, array );
    return item < 3;
});

 1 0 [1, 2, 3, 4]
 2 1 [1, 2, 3, 4]
 3 2 [1, 2, 3, 4]

 result -> false

从运行结果看,当检测第3个元素时,item<3为false, 停止检测,并返回false,这说明every在检测元素时,要求每一个元素都要符合条件item<3,如果有一个不符合就停止检测,并返回false,(ps:你可以测试item<5时的运行结果,返回值一定是true)。那every到底有什么用武之地呢? 当一个for循环使用了break语句后,我们想知道for循环是否正常的执行完时, 我们一般会通过检测for中的索引i==arr.length来判断,因此every的作用就体现在这里。 我们再看看对于every方法的扩展:

if(!Array.prototype.every) {
   Array.prototype.every = function (callback, thisArg) {
        for (var i = 0; i < this.length; i++) {
           if(!callback.call(thisArg,this[i],i,this.toString())){

               return false; //检测到不符合条件的元素,跳出循环,并返回false
           }
        }
        return true; //所有元素都符合条件,返回true
    }
}

indexOf 和 lastIndexOf



这两个方法和String类中indexOf和lastIndexOf作用类似,相信大家对这两个方法用的很熟了,因此这里不多做解释了。

时间: 2024-10-20 11:29:09

ES5新特性:理解 Array 中增强的 9 个 API的相关文章

Spring4.1新特性——Spring缓存框架增强(转)

目录 Spring4.1新特性——综述 Spring4.1新特性——Spring核心部分及其他 Spring4.1新特性——Spring缓存框架增强 Spring4.1新特性——异步调用和事件机制的异常处理 Spring4.1新特性——数据库集成测试脚本初始化 Spring4.1新特性——Spring MVC增强 Spring4.1新特性——页面自动化测试框架Spring MVC Test HtmlUnit简介 Spring4.1新特性——静态资源处理增强 Spring 4.1提供了对jcach

【ElasticSearch】ES5新特性-keyword-text类型-查询区别

ES5新特性-keyword-text类型-查询区别 elasticsearch-head Elasticsearch-sql client junneyang (JunneYang) es keyword_百度搜索 Elasticsearch 5.0 中term 查询和match 查询(text和keyword) - wenbo的博客 - CSDN博客 第三章:ES分词简单说明 - 风之圣痕 - 博客园 elasticsearch的keyword与text的区别 - CSDN博客 原文地址:h

(14)jdk1.5开始的一些新特性:静态导入,增强for循环,可变参数,自动装箱/拆箱,枚举类型

Jdk1.5新特性之静态导入 jdk1.5新特性值静态导入 静态导入的作用:简化缩写 静态导入的作用:可以作用一个类的所有静态成员. 静态导入的格式:import static 包名.类名.静态的成员 import static java.util.Collections.sort; //静态导入指定的某个静态成员方法 import static java.util.Collections.*;  导入所有的静态成员 除了可以导入静态的成员方法,也可以静态的导入成员变量,比如System.out

ABAP 7.50 新特性 – Open SQL中的宿主表达式和其它表达式

在长期的停滞后,Open SQL的发展终于从沉睡中醒来.从ABAP 7.40开始,SAP推进了某些关键的改变,以尽可能地包含SQL92中的特性,并提供与ABAP CDS中的DDL里面的SELECT一样的功能给Open SQL.为了实现这些目标,ABAP运行时环境中引入了一个新的SQL parser作为Open SQL的新基础.结果就是,Open SQL现在可以在ABAP中扮演一些和以往不同的角色了. 虽然在7.40之前,Open SQL更多地被视为ABAP语言本身的一部分,但在同时,SQL关键字

Java8新特性(一)_interface中的static方法和default方法

为什么要单独写个Java8新特性,一个原因是我目前所在的公司用的是jdk8,并且框架中用了大量的Java8的新特性,如上篇文章写到的stream方法进行过滤map集合.stream方法就是接口Collection中的default方法.所以准备专门写写关于java8新特性的文章,虽然现在10已经发布了.但还是要认真的去了解下新版本的变化. static方法 java8中为接口新增了一项功能:定义一个或者更多个静态方法.用法和普通的static方法一样. 代码示例 public interface

手把手教你如何用java8新特性将List中按指定属性排序,过滤重复数据

在java中常常会遇到这样一个问题,在实际应用中,总会碰到对List排序并过滤重复的问题,如果List中放的只是简单的String类型过滤so easy,但是实际应用中并不会这么easy,往往List中放的是一个类,类中有多个属性,要过滤重复数据,而且这个重复数据要按自己指定的属性过滤,但是要想按照其它属性排序顺序过滤,所以要先排序一下,然后按照某个属性过滤. 实体类如下所示,大家只要创建下面的实体类,无需继承父类,大家不会注解式风格的话,请自行加上getter/setter方法. 首先看看gr

温故知新——JS_ ES5新特性简介

ES5浏览器支持情况: 一般来说,除了针对个别特性的特殊说明,各大主流浏览器都支持es5,包括 Chrome 13+ Firefox 4+ Safari 5.1* IE 9* 其中IE9不支持es的严格模式,从IE10开始支持.Safari 5.1不支持Function.prototype.bind. 1.Strict Mode, 即所谓的严格模式. 在一个文件.项目或函数的开头加上"use strict";即开启严格模式. 详细内容参考:参考链接1: 参考连接2: 参考链接3--阮一

ES6新特性:Javascript中的Reflect对象

Reflect介绍: Reflect这个对象在我的node(v4.4.3)中还没有实现, babel(6.7.7)也没有实现 ,新版本的chrome是支持的, ff比较早就支持Proxy和Reflect了,要让node支持Reflect可以安装harmony-reflect ; Reflect不是构造函数, 要使用的时候直接通过Reflect.method()调用, Reflect有的方法和Proxy差不多, 而且多数Reflect方法原生的Object已经重新实现了. 什么要使用Reflect

ES6新特性:Javascript中内置的延迟对象Promise

Promise的基本使用: 利用Promise是解决JS异步执行时候回调函数嵌套回调函数的问题, 更简洁地控制函数执行流程: 通过new实例化Promise,  构造函数需要两个参数, 第一个参数为函数执行成功以后执行的函数resolve, 第二个函数为函数执行失败以后执行的函数reject: new Promise(function(resolve , reject) { }); 通过Promise,我们把回调函数用线性的方式写出来,而不是一层套一层, 这个函数有四层回调: fn("args&