js一些數組的操做。

數組擴展運算符

含義:
擴展運算符是三個點(...);比如rest參數的逆運算,將一個數組轉爲用逗號分割的參數序列。正則表達式

console.log(...[1,2,3]);
//1,2,3
console.log(1,...[2,3,4],5);
//1,2,3,4,5
[...document.querySelectorAll('div')]
//[<div>,<div>]

該運算符主要用於函數調用。數組

function pushs(array,...items){
  array.push(...items);
  return array;
}
console.log(pushs([1,2],...[4,5,6]));
//[1, 2, 4, 5, 6]

function add(x,y){
    return x+y;
}
const numbers = [4,38];
var b = add(...numbers);
//b=42

擴展運算符與正常的函數能夠結合使用,很是靈活。app

function f(v,w,x,y,z){}
const args = [0,1];
f(-1,...args,2,...[3]);

擴展運算符後面還能夠放置表達式函數

const arr =[
    ...(x>0?['a']:[]),
    'b',
]

若是擴展運算符後面是一個空數組,則不產生任何效果。優化

[...[],1]

注意:擴展運算符若是放在括號中,JavaScript引擎就會認爲是函數調用,不然就會報錯。ui

(...[1,2]);
console.log((...[1,2]))

上面兩種狀況都會報錯,由於擴展運算符所在的括號不是函數調用,而console.log(...[1,2])就不會報錯,由於這時是函數的調用。this

  • 替代函數的apply方法
//ES5的寫法
function f(x,y,z){
    //...
}
var args = [0,1,2];
f.apply(null,args);
//ES6的寫法
function f(x,y,z){
    //...
}
let args = [0,1,2];
f(...args);

下面是擴展運算符取代apply方法的一個實際的例子,應用Math.max方法,簡化求出一個數組最大元素的寫法。prototype

// ES5 的寫法
Math.max.apply(null, [14, 3, 77])

// ES6 的寫法
Math.max(...[14, 3, 77])

// 等同於
Math.max(14, 3, 77);

另外一個例子是經過push函數,將一個數組添加到另外一個數組的尾部。rest

//ES5的寫法
var arr1 = [0,1,2];
var arr2 = [3,4,5];
Array.prototype.push.apply(arr1,arr2);
//ES6的寫法
let arr1 = [0,1,2];
let arr2 = [3,4,5];
arr1.push(...arr2);

下面是另外一個例子。code

//ES5
new (Date.bind.apply(Date,[null,2015,1,1]));
//ES6
new Date(...[2015,1,1])
  • 擴展運算符的應用

(1)複製數組

const a1 = [1,2];
//寫法一
const a2 = [...a1];
//寫法二
const [...a2] = a1;
//上面的兩種寫法,a2都是a1的克隆,改變互相不影響。

(2)合併數組

const a1 = [{ foo: 1 }];
const a2 = [{ bar: 2 }];

const a3 = a1.concat(a2);
const a4 = [...a1, ...a2];

a3[0] === a1[0] // true
a4[0] === a1[0] // true
//上面代碼中,a3和a4是用兩種不一樣方法合併而成的新數組,可是它們的成員都是對原數組成員的引用,這就是淺拷貝。若是修改了原數組的成員,會同步反映到新數組。
(3)與解構賦值結合
擴展運算符能夠與解構賦值結合起來,用於生成數組。

//ES5
a=list[0],rest=list.slice(1);
//ES6
[a,...rest] = list

const [first, ...rest] = [1, 2, 3, 4, 5];
first // 1
rest  // [2, 3, 4, 5]

const [first, ...rest] = [];
first // undefined
rest  // []

const [first, ...rest] = ["foo"];
first  // "foo"
rest   // []

若是將擴展運算符用於數組賦值,只能放在參數的最後一位,不然會報錯。

const [...butLast, last] = [1, 2, 3, 4, 5];
// 報錯

const [first, ...middle, last] = [1, 2, 3, 4, 5];
// 報錯

如何從數組中按順序取每5個元素爲一組放到新數組中,最後不夠5個也存爲一個數組

//1.
var SplitArray = function(cont,arr){
    var newArr =[];
    var f;
    for(f=0;f<arr.length;) newArr.push(arr.slice(f,f+=cont))
    return newArr;
};
var arr = [1,2,3,4,545,6,57,67,87,8,98,98,090,0,32,43,45,45,6,7,67,8,78,8];
console.log(SplitArray(5,arr))
//2.
var data = [
    {name:'li'},
    {name:'si'},
    {name:'zi'},
    {name:'ai'},
    {name:'wi'},
    {name:'hi'},
    {name:'ei'},
    {name:'ti'},
    {name:'yi'},
    {name:'ui'},
    {name:'ii'},
]
var result =[];
for(var i=0;i<data.length;i+=3){
    result.push(data.slice(i,i+3));
}
console.log(result);

斐波那契數列

//1.使用generator函數和for...of實現
function*fibonaci(){
    let[prev,curr] = [0,1];
    for(;;){
        yield curr;
        [prev,curr] = [curr,prev+curr];
    }
}
for(let n of fibonaci()){
    if(n>1000)break;
    console.log(n);
}
//2.遞歸方法基礎上進行尾調用優化:
function fb(n,res1=1,res2=1){
  if(n<=2){
    return res2;
  }else{
    return fb(n-1,res2,res1+res2);
  }
}
var a = fb(10);

//3.迭代
function fb(n){
  var res1=1;
  var res2=1;
  var sum = res2;
  for(var i=2;i<n;i++){
    sum = res1+res2;
    res1 = res2;
    res2 = sum;
  }
  return sum;
}
var a = fb(10);
console.log(a)

var temp;
var res1 =1;
var res2 =1;
for(var i=2;i<=10;i++){
  //先把res2賦值給一個變量保存下來。
  temp = res2;
  //res2從新賦值等於res1+res2;
  res2 = res1+res2;
  //再把保存的temp賦值給res1,保證下次循環的時候res1等於上次循環res2未改變時的值
  res1 = temp;
}

slice()和splice()區別

slice(start,end)
start:必需。規定從何處開始選取。若是是負數,那麼它規定從數組尾部開始算起的位置。也就是說,-1指最後一個元素,-2指倒數第二個元素,以此類推。
end:可選。規定從何處結束選取。該參數是數組片斷結束處的數組下標。若是沒有指定該參數,那麼切分的數組包含從start到數組結束的全部元素。若是這個參數是負數,那麼它規定的是從數組尾部開始算起的元素。
返回一個新的數組,包含從start到end(不包括該元素)的arrayObject中的元素。
注意:該方法並不會修改數組,而是返回一個子數組。若是想刪除數組中的一段元素,應該使用方法Array.splice().

var a =[1,2,3,4,5,6]
//若是不傳入參數二,那麼將從參數一的索引位置開始截取,一直到數組尾
console.log(a.slice(0,3))//1,2,3
console.log(a.slice(2))//3,4,5,6
//若是兩個參數中的任何一個是負數,array.length會和它們相加,試圖讓它們成爲非負數,舉例說明:
//當只傳入一個參數,且是負數時,length會與參數相加,而後再截取
//當只傳入一個參數,是負數時,而且參數的絕對值大於數組length時,會截取整個數組
console.log(a.slice(-1))//6
console.log(a.slice(-2))//5,6
console.log(a.slice(-3))//4,5,6
//當傳入兩個參數一正一負時,length也會先於負數相加後,再截取
console.log(a.slice(-3,6))//4,5,6
console.log(a.slice(-3,5))//4,5
console.log(a)//1,2,3,4,5,6
//當傳入一個參數,大於length時,將返回一個空數組

splice()方法向/從數組中添加/刪除項目,而後返回被刪除的項目。
該方法會改變原始數組。
arrayObject.splice(index,howmany,item1,...,itemX)
index:必需,整數,規定添加/刪除項目的位置,使用負數可從數組結尾處規定位置。
howmany:必需。要刪除的項目數量。若是設置爲0,則不會刪除項目。
item1,...,itemX:可選。向數組添加的新項目。
返回值:包含被刪除項目的新數組,若是有的話。

var arr = ['a','b','c','d','e'];
// console.log(arr.splice(1,2));//[b,c]
// console.log(arr);//[a,d,e]
// console.log(arr.splice(1,2,'bb','cc'));//[b,c]
// console.log(arr)//[a,bb,cc,d,e]
console.log(arr.splice(1,2,'bb','cc','dd','ee'));//[b,c]
console.log(arr)//["a", "bb", "cc", "dd", "ee", "d", "e"]

split與join

split()方法用於把一個字符串分割成字符串數組。stringObject.split(separator,howmany)。
separator:必需。字符串或正則表達式,從該參數指定的地方分割stringObject。
howmany:可選。該參數可指定返回的數組的最大長度。若是設置了參數,返回的子串不會多於這個參數指定的數組。若是沒有設置該參數,整個字符串都會被分割,不考慮它的長度。
返回值:一個字符串數組。該數組是經過在separator指定的邊界處將字符串stringObject分割成子串建立的。返回的數組中的字串不包括separator自身。
可是,若是separator是包含子表達式的正則表達式,那麼返回的數組中包括與這些子表達式匹配的字串(但不包括與整個正則表達式匹配的文本)
join()方法用於把數組中的全部元素放入一個字符串。元素是經過指定的分隔符進行分隔的。
arrayObject.join(separator)。
separator:可選。指定要使用的分隔符。若是省略該參數,則使用逗號做爲分隔符。
返回值:返回一個字符串。該字符串是經過把arrayObject的每一個元素轉換爲字符串,而後把這些字符串連接起來,在兩個元素之間插入separator字符串而生成的。

map遍歷

array.map(callback,[thisObject]);
map方法的做用不難理解,映射,也就是原數組被映射成對應新數組。下面這個例子是數值項求平方:

var data = [1,2,3,4];
var arrayOfSquares = data.map(function(item){return item*item});
alert(arrayOfSquares)//1,4,9,16

callback須要有return值,若是沒有,就像下面這樣:

var data = [1,2,3,4];
var arrayOfSquares = data.map(function(){});
arrayOfSquares.forEach(console.log());

concat()

Array.concat(),建立並返回一個新數組。

var a = [1,2,3];
var b = a.concat(4,5);
var c = a.concat([4,5]);
console.log(a);//[1,2,3];
console.log(b);//[1,2,3,4,5];
console.log(c);//[1,2,3,4,5];

這個方法還能夠用來複制數組。

var a = [1,2,3];
var b = a.concat();
console.log(a)//[1,2,3];
console.log(b)//[1,2,3];

push()方法與pop()方法

push()方法在數組的尾部添加一個或多個元素,並返回數組的新長度。注意的是,改變的是原數組的值,返回的是新數組的長度。
pop()方法刪除數組的最後一個元素,並返回它的刪除值。也是改變原數組,返回的是刪除的值。

unshift()方法與shift()方法

unshift()方法相似於push()不一樣的是,它是在數組的頭部添加,其它都同樣。
shift()方法則類比pop()方法。

toString()和toLocaleString()

toString()方法將每一個元素轉化爲字符串,相似於不傳參數的join()方法。
toLocaleString()方法是toString()的本地化版本。

forEach()方法,從頭到尾遍歷數組,爲每一個元素調用指定的函數

var a =[1,2,3,4,5];
var sum = 0;
a.forEach(function(value){
    sum+=value;
})
console.log(sum);//sum = 15;

filter()方法,返回的是調用數組的一個子集

var a = [1,2,3,4,5];
var b = a.filter(function(value){
    return value > 3;
})
console.log(b)//返回[4,5];
注意:若是使用map()方法,返回的是[false,false,false,true,true]
filter()會跳過悉數數組中缺乏的元素,它的返回數組老是稠密的。因此能夠用如下方法來壓縮稀疏數組的空缺。
var a = [1,2,,,5];
var b = a.filter(function(value){
    return true;
})
console.log(b)//返回[1,2,5]

every()和some()

every()方法是隻有數組中全部元素都知足某個條件纔會返回true;some()方法是隻要有知足條件的值,就返回true。

var a = [1,2,3,4,5];
a.every(function(value){
    return value <10;
})//true
a.every(function (value){
    return value%2 ===0;
})//false

indexOf()和lastIndexOf()

這兩個方法都是用來搜索整個數組中具備給定值的元素,返回找到的第一個元素的索引,若是沒找到,則返回-1.區別在於indexOf()從頭到尾搜索,然後者則是反向搜索。

相關文章
相關標籤/搜索