javascript中的那些遍历的方法

1、前言

javascript里面有关遍历的方法有多种,这里我就总结一下,使可以直观的了解每种方法是怎么使用的。不论是前端仍是后端都会涉及到对数据的处理。通常来讲,数据常常会以数组或者对象的形式存放在数据库中,这就意味着咱们常常要对数组或者对象进行操做,而对数组或者对象进行操做,遍历必然少不了。下面在介绍遍历的方法以前,我会先介绍一下数据类型以及内存模型等一些相关的知识。javascript

2、关于数据类型以及内存模型

1.分类

ECMAScript的数据类型分为:前端

基本数据类型(NumberStringBooleanUndefinedNullSymbol(ES6)java

引用数据类型(ObjectArrayFunctionRegExpDateError程序员

两种数据类型的区别:存储位置不一样es6

2.栈(stack)和堆(heap)

栈(stack):一种先进后出的数据结构,由操做系统(编译器)自动分配,释放的内存空间。算法

堆(heap):一种树形数据结构,通常由程序员分配(经过new关键字),释放的动态内存空间, 若程序员不释放,程序结束后由系统虚拟机的垃圾回收算法来决定是否回收。数据库

3.内存模型

内存模型与语言有关系json

栈区:存放es5中基本数据类型、引用数据类型的引用后端

堆区:存放数组,对象等引用数据类型自己数组

变量区:五种数据类型数据自己

代码区:函数体的二进制代码

注意:

  • 栈区对应着堆区,变量区,代码区这三个区,他们数据的引用均存放在栈区中。

  • 栈区存放的是空间小,大小固定的,频繁被使用的数据,读取速度快。

  • 堆区存放的是空间大,大小不固定的数据,若是这些数据存放在栈区将影响程序的性能。

  • 引用数据类型的指针存在栈区,该指针指向堆区该实体的起始地址,当解释器寻找引用值时,会首先检索其

    在栈中的地址,取得地址后从堆中得到实体。

4.基本数据类型的声明与赋值是怎样一个过程

//es6的变量声明
let num = 111;
复制代码

执行这段代码会通过这些过程

1.建立惟一标识符 num

2.在内存变量区分配一个空间,并将该空间的地址0034HHH(假设)存在栈区

3.在变量区分配的空间里存一个值111

咱们认为标识符num等于地址0034HHH,这个地址的空间里保存着一个值111

如今执行下面代码

let num = 111;
	num = num+1;
console.log(num);//112
复制代码

在这个过程最后打印的num的地址是否仍是0034HHH,而保存的值是112?并非的

执行let num=num+1的时候,系统从新分配了一个空间,而且num等于这个新空间的地址(0064HBC),新的空间保存的值为112

注意:在es6里面,与let不一样的是,const声明的常量,其地址是不会变的,所以不容许从新赋值且必须赋初始值

3、关于数组

ArrayJavascript 中是一个对象,与其余语言的Array是有区别的。在JavaScriptArray的索引是属性名。Javascript中的 Array在内存上并不连续,其次, Array 的索引并非指偏移量。实际上, Array 的索引也不是 Number 类型,而是String 类型的。咱们能够正确使用如arr[0] 的写法的缘由是语言能够自动将Number类型的 0 转换成 String类型的 “0″ 。因此,在Javascript中历来就没有 Array的索引,而只有相似 “0″ 、 “1″ 等等的属性。每一个 Array 对象都有一个 length 的属性,这一点与其余语言的Array很像,可是length 属于不可枚举属性,实际上, Array 对象还有许多其余不可枚举的属性。

4、关于对象

关于JavaScript中的对象,我以前的文章js对象与对象原型中有详细的介绍

5、关于判断数据类型的方法

1.typeof

用于检查数据类型,其返回值为字符串类型,返回值有numberstringundefinedfunctionobject

须要特别注意的是:typeof(NAN)-->undefinedtypeof([],{},null)-->object

2.instanceof

用于判断一个实例对象是否是由这个构造函数实例化出来的,若是是,则返回true,不然返回false,如:p instanceof Person

3.原型中的构造器

若是p._proto_.constructor==Person.prototype.constructor,说明实例对象p是由构造函数Person实例化出来的

4.toString.call(value)

鉴于typeof用于判断数据类型的局限性,toString.call()能够准确的判断数据类型

6、什么状况下才能改变数组或者对象的值

在实际的项目中,会有这样的需求,从接口获取到的数组或者对象格式的数据须要经过遍历,而且在遍历的过程作一些操做去改变原来的值,可是有的状况下就仅仅是简单的遍历而已。那么这里涉及到什么样的操做才会改变原数组或者对象的值呢?

1.改变原数组

下面,咱们先来看看两个对比的例子

//操做一
var arr=[1,2,3];
for(var i=0,len=arr.length;i<len;i++){
    arr[i]*2;
}
console.log(arr);//(3) [1, 2, 3]
复制代码

以上操做,原来数组的值并无变化

//操做二
var arr=[1,2,3];
for(var i=0,len=arr.length;i<len;i++){
    arr[i]=arr[i]*2;//经过引用从新赋值
}
console.log(arr);//(3) [2, 4, 6]
复制代码

以上操做发现,原来数组的值改变了,这是为何?上面我有介绍过基本数据类型的声明与赋值过程,能够发现值的改变很大程度实际上是地址的改变,上面经过引用从新赋值,因此原数组的值改变了。

2.改变对象的值

json={
    name:'xiaoming',
    sex:'男',
    age:22
}
json.age=json.age+1;
console.log(json);//{name: "xiaoming", sex: "男", age: 23}
复制代码

以上操做发现,对象 json 的 age 的值被改变了,不论是数组仍是对象,都是经过索引或者键值对中的键来找到相应的值的,而索引或者键就是引用也就是地址,因此不论是数组仍是对象,值的改变操做必定要涉及到地址的改变,原来的值才会被改变。

7、有关遍历的方法

1.for()

做用:for循环是最基础的遍历方法,通常用来遍历数组,单纯的遍历,不会改变原数组的值

var arr = [1, 2, 3];
for(var i = 0, len = arr.length; i < len; i++) {
    console.log(typeof i)//number
    console.log(arr[i]);//1 2 3
}
console.log(arr);//(3)[1,2,3]
复制代码

注意:

  • i 是索引,number 类型

  • 为了不遍历过程重复获取数组长度,应使用临时变量,将长度缓存起来

  • 没有返回值

  • 若是在遍历的过程从新赋值,那必然是会改变数组原来的值的

    var arr = [1, 2, 3];
    for(var i = 0, len = arr.length; i < len; i++) {
        arr[i]=arr[i]*2;
    }
    console.log(arr);//(3)[2,4,6]
    复制代码

2.for in

做用:for in 能够遍历数组,对象的属性,也能遍历原型链上的属性(最后遍历),istring类型

遍历数组

在JavaScript中,数组中的索引,相似 “0″ 、 “1″ 等等的属性

var arr=['h','e','l','l','o'];
for(var i in arr){
    console.log(typeof i)//string
	console.log(arr[i]);//h e l l o
}
console.log(arr);//(5)['h','e','l','l','o']
复制代码

注意:

  • i 为索引(属性),string 类型

  • 若是在遍历过程从新对数组进行赋值,也是会改变数组原来的值的

    const arr = [1, 2, 3];
    for(var i = 0, len = arr.length; i < len; i++) {
        arr[i]=arr[i]*2;
    }
    console.log(arr);//(3)[2,4,6]
    复制代码
  • 若是原来的数组扩展了私有属性,那么会在最后把数组的私有属性遍历出来,基于这一点,通常不会使用 for in 来遍历数组

    var arr=['h','e','l','l','o'];
    arr.a='world';//扩展私有属性
    for(var i in arr){
    	console.log(arr[i]);
    }
    console.log(arr);//(5) ["h", "e", "l", "l", "o", a: "world"]
    复制代码
遍历对象
json={
    name:'xiaoming',
    sex:'男',
    age:22
}
for(var i in json){
    console.log(json[i]);//xiaoming 男 22
}
console.log(json);//{name: "xiaoming", sex: "男", age: 22}
复制代码

注意:

  • i 为属性,string类型

  • for in 会将对象的属性遍历出来

  • 若是在遍历的过程从新赋值,会改变原来的值

    json={
        name:'xiaoming',
        sex:'男',
        age:22
    }
    for(var i in json){
        json[i]=json[i]+'1111';
    }
    console.log(json);//{name: "xiaoming111", sex: "男111", age: 22111}
    复制代码
  • 若是在对象原型上添加属性,会在最后遍历出来

    function Person(name,age) {
        this.name=name;
        this.age=age;
    }
    //经过原型添加属性
    Person.prototype.sex='男'
    
    var p=new Person("小明",20);
    for(var i in p){
        console.log(p[i]);//小明 20 男
    }
    console.log(p);//Person {name: "小明", age: 20}
    复制代码

3.for of

做用:for of 通常与 for in 造成对比,功能与 for in 相似,可是不能用来遍历对象

var arr=[1,2,3];
//for in 遍历数组
for(let i in a){
	console.log(i);//0 1 2
	console.log(a[i]);//1 2 3
}
//for of 遍历数组
var arr=[1,2,3];
for(let i of arr){
	console.log(i);//1 2 3
}
复制代码

注意:

  • for in 的 i 是索引(属性),for of 的 i 是数组中元素

4.forEach()

做用:forEach ( ) 方法用于调用数组的每一个元素,并将元素传递给回调函数,回调函数一个有三个参数。

语法:array.forEach(function(item, index, arr), thisValue)

参数:

参数 描述
item 必需,当前元素
index 可选,当前元素的索引值
arr 可选,当前元素所属的数组对象
thisValue 可选,传递给函数的值通常用 "this" 值,若是这个参数为空, "undefined" 会传递给 "this" 值
var arr=['a','b','c','d'];
arr.forEach(function(item,index,arr){
    console.log(item,index);
    //a,0
    //b,1
    //c,2
    //d,3
});
console.log(arr);//(4) ["a", "b", "c", "d"]
复制代码

注意:

  • forEach( ) 没有返回值,对 return 不起做用

  • 回调函数内部不能有break,continue的,不然会报错的

  • 遍历过程不必定会改变原数组的值,具体要看是否涉及到地址的操做

    var arr=[1,2,3];
    arr.forEach(item => {
        item = item * 2;//未涉及地址操做
    })
    console.log(arr);//(3) [1,2,3]
    复制代码
    var arr=[1,2,3];
    arr.forEach((item,index) => {
        arr[index] = item * 2;//涉及地址操做
    })
    console.log(arr);//(3) [2, 4, 6]
    复制代码
    var arr = [
        {name:'xiaoming',age:16},
        {name:'zhangsan',age:17}
    ];
    arr.forEach(item => { 
        item.age = item.age + 1;//涉及地址操做
    });
    console.log(arr);//(2) [{name:'xiaoming,age:17'}, {name:'zhangsan',age:'18'}]
    复制代码

5.map()

做用:map ( ) 方法按照原始数组元素顺序依次处理元素,返回一个新数组,新数组中的元素为原始数组元素调用函数处理后的值

语法:array.map(function(item,index,arr ), thisValue)

参数:

参数 描述
item 必须,当前元素的值
index 可选,当前元素的索引值
arr 可选,当前元素属于的数组对象
thisvalue 可选,对象做为该执行回调时使用,传递给函数,用做 "this" 的值。若是省略了 thisValue,或者传入 null、undefined,那么回调函数的 this 为全局对象。
var arr = [1,2,3];
var temp=arr.map((item,index)=>{
    console.log(item,index);
    //1 0
    //2 1
    //3 2
})
console.log(temp);//(3) [undefined, undefined, undefined]
console.log(arr);//(3)[1,2,3]
复制代码
var arr = [1,2,3];
var temp=arr.map(item=>{
	return item*2;
})
console.log(temp);//(3) [2, 4, 6]
console.log(arr);//(3) [1, 2, 3]
复制代码

注意:

  • map( ) 不会对空数组进行检测

  • map( ) 不会改变原始数组

  • 每一个元素都会执行相应的回调函数,必需要有返回值,不然结果为 undefined

    var arr = [10,2,5,22,65,44,32];
    var temp=arr.map((item,index)=>{
        console.log(item);//10,2,5,22,65,44,32
        if(item>30){
        	return item;
        }
    })
    console.log(temp);//(7) [undefined, undefined, undefined, undefined, 65, 44, 32]
    console.log(arr);//(7) [10, 2, 5, 22, 65, 44, 32]
    复制代码

6.filter ( )

做用:filter() 是个过滤器,该方法建立一个新的数组,新数组中的元素是经过检查原数组中符合条件的全部元素。

语法:array.filter(function(item,index,arr), thisValue)

参数:

参数 描述
item 必需,当前元素
index 可选,当前元素的索引值
arr 可选,当前元素所属的数组对象
thisValue 可选,传递给函数的值通常用 "this" 值,若是这个参数为空, "undefined" 会传递给 "this" 值
var arr = [1,2,3];
var temp=arr.filter((item,index)=>{
    console.log(item,index);
    //1 0
    //2 1
    //3 2
})
console.log(temp);//(3) []
console.log(arr);//(3)[1,2,3]
复制代码
var arr = [1,2,30,11,3];
var temp=arr.filter((item)=>{
	console.log(item);//1,2,30,11,3
	return item>10
})
console.log(temp);//(2) [30, 11]
console.log(arr);//(5) [1, 2, 30, 11, 3]
复制代码
//数组去重
var arr=['apple','pear','apple','banana'];
var r=arr.filter(function(item,index,self){
	return self.indexOf(item)===index;
})
复制代码

注意:

  • filter() 不会对空数组进行检测
  • filter() 不会改变原始数组
  • 每一个元素都会执行相应的回调函数,须要 return
  • indexOf ( ) 能够返回某个指定的子字符串在字符串中首次出现的位置,检索的字符串若是没有出现,则返回-1

7.find ( )

做用:find() 方法返回知足回调条件的指定数组的第一个元素的值,数组中的元素依次执行回调函数,当数组中的元素知足条件时, find() 返回符合条件的元素,以后的元素再也不执行函数,若是都没有符合条件的元素返回 undefined

语法:array.find(function(item, index, arr),thisValue)

参数:

参数 描述
item 必需,当前元素
index 可选,当前元素的索引值
arr 可选,当前元素所属的数组对象
thisValue 可选,传递给函数的值通常用 "this" 值,若是这个参数为空, "undefined" 会传递给 "this" 值
var arr = [1,2,3];
var temp=arr.findIndex((item,index)=>{
    console.log(item,index);
    //1 0
    //2 1
    //3 2
})
console.log(temp);//undefined
console.log(arr);//(3)[1,2,3]
复制代码
var arr = [1,2,30,11,3];
var temp=arr.find((item)=>{
	console.log(item);//1,2,30
	return item>10
})
console.log(temp);//30
console.log(arr);//(5) [1, 2, 30, 11, 3]
复制代码
var arr = [1,2,30,11,3];
var temp=arr.find((item)=>{
	console.log(item);//1,2,30,11,3
	return item>100
})
console.log(temp);//undefined
console.log(arr);//(5) [1, 2, 30, 11, 3]
复制代码

注意:

  • find() 不会对空数组进行检测
  • find() 不会改变原始数组
  • 返回值为数组中的元素,不是索引

8.findIndex()

做用:findIndex() 方法返回知足回调函数条件的指定数组的第一个元素的索引,没有符合条件则返回-1。

语法:array.findIndex(function(item, index, arr), thisValue)

参数:

参数 描述
item 必需,当前元素
index 可选,当前元素的索引值
arr 可选,当前元素所属的数组对象
thisValue 可选,传递给函数的值通常用 "this" 值,若是这个参数为空, "undefined" 会传递给 "this" 值
var arr = [1,2,3];
var temp=arr.findIndex((item,index)=>{
    console.log(item,index);
    //1 0
    //2 1
    //3 2
})
console.log(temp);//-1
console.log(arr);//(3)[1,2,3]
复制代码
var arr = [1,2,30,11,3];
var temp=arr.findIndex((item)=>{
	console.log(item);//1,2,30
	return item>10
})
console.log(temp);//2
console.log(arr);//(5) [1, 2, 30, 11, 3]
复制代码

注意:

  • findIndex() 不会对空数组进行检测

  • findIndex() 不会改变原始数组

  • 并非数组中全部的元素都执行回调函数,当数组中的元素一旦知足条件时, findIndex() 返回符合条件的元素的索引,以后的元素不会再执行回调函数

9.some ( )

做用:some() 方法用于检测数组中的元素是否知足指定条件,会依次执行数组的每一个元素,若是有一个元素知足条件,则表达式返回 true , 剩余的元素不会再执行检测,若是没有知足条件的元素,则返回false

语法:array.some(function(item,index,arr),thisValue)

参数:

参数 描述
item 必需,当前元素
index 可选,当前元素的索引值
arr 可选,当前元素所属的数组对象
thisValue 可选,传递给函数的值通常用 "this" 值,若是这个参数为空, "undefined" 会传递给 "this" 值
var arr = [1,2,3];
var temp=arr.some((item,index)=>{
    console.log(item,index);
    //1 0
    //2 1
    //3 2
})
console.log(temp);//false
console.log(arr);//(3)[1,2,3]
复制代码
var arr = [1,2,30,11,3];
var temp=arr.some((item)=>{
	console.log(item);//1,2,30
	return item>10
})
console.log(temp);//true
console.log(arr);//(5) [1, 2, 30, 11, 3]
复制代码

注意:

  • some ( ) 不会对空数组进行检测

  • some ( ) 不会改变原始数组

  • 并非数组中全部的元素都执行回调函数,当数组中的元素一旦知足条件时,结果返回 true,以后的元素再也不执行了

10.every ( )

做用:every() 方法用于检测数组全部元素是否都符合指定条件,会依次执行数组中的每一个元素,若是数组中检测到有一个元素不知足,则整个表达式返回 false ,且剩余的元素不会再进行检测,只有全部元素都知足条件,则返回 true

语法:array.every(function(item,index,arr), thisValue)

参数:

参数 描述
item 必需,当前元素
index 可选,当前元素的索引值
arr 可选,当前元素所属的数组对象
thisValue 可选,传递给函数的值通常用 "this" 值,若是这个参数为空, "undefined" 会传递给 "this" 值
var arr = [1,2,3];
var temp=arr.every((item,index)=>{
    console.log(item,index);//1 0
})
console.log(temp);//false
console.log(arr);//(3)[1,2,3]
复制代码
var arr = [1,2,30,11,3];
var temp=arr.every((item)=>{
	console.log(item);//1,2,30,11,3
	return item>0
})
console.log(temp);//true
console.log(arr);//(5) [1, 2, 30, 11, 3]
复制代码

注意:

  • every ( ) 不会对空数组进行检测

  • every ( ) 不会改变原始数组

  • every ( ) 与 some ( ) 造成比较

相关文章
相关标签/搜索