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 ( ) 造成比較

相關文章
相關標籤/搜索