180326 數組

概述

  • 數組是值的有序集合,其中值稱作‘元素’,對應位置稱作‘索引’
  • 數組繼承Array.prototype中的屬性
  • 數組是對象的特殊形式,數組索引實際上和碰巧是整數的屬性名差不多

創建數組

  • 數組直接量
var arr = [1,2,'a'];

var arr1 = [[1,{x:1,y:2}],[2,{x:3,y:4}]];
// 可以包含對象直接量或其他數組直接量。

var arr2 = [1, , ,2, ,'a', ,0];
//稀疏數組 arr2[2] = undefined  arr.length = 8
//如果省略數組直接量中的某個值,省略的元素將被賦予undefined值

var arr3 = [ , , ];
//兩個元素undefined 數組直接量結尾的逗號可選擇
  • 調用構造函數
=1= 調用時沒有參數
var a = new Array();
//相當於var a = [];

=2= 調用時有一個數值參數(一個數,整數),它指定數組長度
var a = new Array(10);

=3= 顯示指定兩個以上的數組元素或非數值元素
var a = new Array('test');
var a = new Array(5,4,3,2,1,'testing');
  • 比較
var a = [8];
var b = new Array(8);
console.log(a);
console.log(b);
console.log(a.length);
console.log(b.length);

這裏寫圖片描述


  • 刪除
=1= delete

var a = [1,'a',3, ,'b',6];
console.log(a,a.length);
delete a[1];
// 刪除盒子裏的東西,盒子還在
console.log(1 in a);
console.log(a,a.length);
// 從數組中刪除一個元素,它就變成稀疏數組
-----------------------------------------------
=2= 新的期望數組長度
var a = [1,2,3,4,5,6,7];
console.log(a,a.length);
a.length = 4;
console.log(a,a.length);

這裏寫圖片描述

這裏寫圖片描述


判斷數組的方法:

  1. instanceof
  2. object.prototype.toString (跨域常用)
  3. constructor

數組讀寫

var a = [1,2];
console.log(a[9]);
//溢出讀沒意義

var b = ['a','b'];
b[10] = 9;
console.log(b);
//可以溢出寫

這裏寫圖片描述

  • 數組是特殊的對象,索引都是屬性名。 數組[索引] -> 對象[屬性]
  • 但只有0~2e32-2之間的整數屬性名纔是索引。
  • 所有的數組都是對象,可以爲其創建任意名字的屬性。
  • 但如果使用的屬性是數組的索引,數組的特殊行爲就是將根據需要更新length屬性值。
  • 可以使用負數或非整數來索引數組。這時候數值轉化爲字符串,字符串作爲屬性名使用,此時當做對象的屬性看待。
  • 特別的,使用 非負整數的字符串,則會當做數組索引。
function roc(a,prop){
    console.log(a[prop]);
    console.log(a);
    console.log(a.length);
}
var a = [];
a[1] = 1;
roc(a,1.000);
a[-1.23] = true;
roc(a,-1.23);
a['1000'] = 0;
roc(a,'1000');

稀疏數組

  • 稀疏數組就是包含從0開始的不連續索引的數組。
a = new Array(5);  // 數組沒有元素,但是數組長度是5
a = [];   // 創建一個空數組,數組長度是0
a[1000] = 0; // 賦值添加一個元素,但是設置長度爲1001
  • 當省略數組直接量中的值時(使用連續逗號),這時多得到的數組也是稀疏數組,省略掉的值是不存在的。
  • 通過調用構造函數創建數組,創建的是稀疏數組,數組元素根本不存在。
var a1 = [, , , ];
var a2 = new Array(3);
var a3 = [undefined, , , ];
console.log(a1);
console.log(a2);
console.log(a3);
console.log(0 in a1);
console.log(0 in a2);
console.log(0 in a3);

這裏寫圖片描述


數組長度

數組的特殊行爲

  • 當索引i大於或等於現有數組的c長度時,length屬性的值將設置爲i + 1;
  • 設置length屬性爲一個小於當前長度的非負整數n時,當前數組中索引值大於或等於n的元素將從中刪除。

添加和刪除數組元素

  • 爲新索引賦值
var a = [];
a[2] = 9

push()方法(改變原數組)

從尾部加入元素

  • 作用:尾部插入元素,增加數組長度
  • 參數:推入的值
  • 返回值:數組長度

    組合使用push()pop()可以實現先進後出的棧

var arr = [1];
console.log(arr,arr.push(2,3,4));
// [1,2,3,4] 4

//模擬源碼實現push功能
var arr = [1, 2];
Array.prototype.myPush = function() {
    for (var i = 0; i < arguments.length; i++) {
        this[this.length] = arguments[i];
    }
    return this.length;
}
arr.myPush('a', 'b', 'c');
arr.myPush('d', 'e');

pop()方法(改變原數組)

彈出最後一個元素的值

  • 作用:刪除數組最後一個元素,減小數組長度
  • 返回值:彈出的值
var arr = [1,2,3,4];
console.log(arr,arr.pop());
// [1,2,3] 4

//模擬源碼實現pop功能
Array.prototype.myPop = function() {
    var val = this[this.length - 1];
    this.length -= 1;
    return val;
}
arr.myPop();
var arr = [1, 2, 3, 4];
var a = arr.pop();
console.log(a, arr, arr.length);
// 使用pop方法,數組長度減少

這裏寫圖片描述


unshift()方法 (改變原數組)

頭部插入一個元素

  • 參數:插入元素
  • 返回值:數組長度

    與splice()一樣,參數是一次性插入的,插入順序和在參數列表中的參數一致。

var arr = [1, 2, 3];
arr.unshift('a', 'b', 'c');

var arr = [1, 2, 3];
Array.prototype.myUnshift = function() {
   var newArr = [];
   for (var i = 0; i < arguments.length + this.length; i++) {
       newArr[i] = i < 2 ? arguments[i] : this[i - arguments.length];
       //新數組 = 新增的類數組 + 原數組
       //new[i = 0] = arguments[0]
       //new[i = 1] = arguments[1]
       //new[i = 2] = arr[i - arguments.length] 
       //new[i = 3] = arr[i - arguments.length]
       //i < 2 + 3 
   }
   for (var i = 0; i = newArr.length; i++) {
       this[i] = newArr[i];
   }
   return this.length;
}
// arr.myUnshift('a', 'b');

這裏寫圖片描述


shift()方法 (改變原數組)

彈出頭部第一個元素

  • 返回值:彈出元素
var arr = ['a','b','c'];
console.log(arr);
console.log(arr,arr.shift());
//shift同樣改變數組長度

這裏寫圖片描述

這裏寫圖片描述


splice()方法(改變原數組)

指定位置插入刪除

  • 作用:指定位置 插入、刪除元素
  • 參數:
    • 第一個參數:插入/刪除起始位置
    • 第二個參數:指定從起始位置刪除元素的個數(0不刪 | 不填全刪)
    • 第三個參數:新插入的元素 本身(若插入元素是數組,區別於concat(),會插入數組本身)
  • 返回值:被刪除的元素數組
var a = [1,2,3,4,5,6,7,8];
a.splice(4);//第二個參數沒填,起始位置後全刪
a.splice(1,2);//第三個參數沒填,僅刪除元素
a.splice(1,1);//在原數組上改變

這裏寫圖片描述

var a = [1,2,3,4,5];
a.splice(2,0,'a','b');//不刪除
a.splice(2,2,[1,2],3);//插入數組本身

這裏寫圖片描述


數組遍歷

  • for
var arr = [1, 2, 3, 4, 5, 6, 7, 8];
var keys = Object.keys(arr);
var values = [];
for (var i = 0 , len = keys.length; i < len; i++) {
//優化,數組的長度只查詢一次
    var key = keys[i];
    values[i] = arr[key];
}
console.log(values);
  • 探究

    • Object.keys()方法 (傳入對象、數組 返回屬性名、索引)

      Object.keys() 方法會返回一個由一個給定對象的自身可枚舉屬性組成的數組,數組中屬性名的排列順序和使用 for…in 循環遍歷該對象時返回的順序一致 (兩者的主要區別是 一個 for-in 循環還會枚舉其原型鏈上的屬性)。
      這裏寫圖片描述

var arr = [1, , 3, 4, , 6, 7, 'a'];
var roc = Object.keys(arr); //返回索引,是一個數組
console.log(roc);
var newArr = [];
for (var i = 0, len = roc.length; i < len; i++) {
    // 此處遍歷len = 6 , i = 0 ~ 5
    newArr[i] = arr[i];

    // nA[0]=arr[0]=1 
    // nA[1]=arr[1]=(empty->undefined) 
    // nA[2]=arr[2]=3
    // why不直接將原數組的索引對應值直接賦值新數組
}
console.log(newArr);
console.log(1 in newArr);
newArr[2] = 100;  // 猜測正確,空賦值給新數組,變成undefined,但此時該索引上存在元素
console.log(newArr);
console.log(arr);
console.log(1 in arr); // 原本就是空數組

這裏寫圖片描述

var arr = [1, , 3, 4, , 6, 7, 'a'];
var roc = Object.keys(arr); 
console.log(roc);
var newArr = [];
for (var i = 0, len = roc.length; i < len; i++) {
    var rocs = roc[i];
    newArr[i] = arr[rocs];
}
console.log(newArr);
console.log(1 in newArr);

newArr[2] = 100;
console.log(newArr);
console.log(arr);
console.log(1 in arr);

// === 過濾稀疏數組,遍歷後得到 ===

這裏寫圖片描述

  • forEach

    • 從頭至尾遍歷數組,爲每個數組調用指定函數
    • 可以傳三個參數:數組元素,索引,數組本身
    • 如果只關心數組元素的值,可以只寫一個參數
var data = [1, 2, 3, 4, 5];
var sum = 0;
data.forEach(function(value) {
    sum += value;//將每個值累加到sum上
});
console.log(sum);

data.forEach(function(v, i, a) {
    a[i] = v + 1; //每個元素的值自加1
});
console.log(data);
var a = [1, 2, 3, 4, 5, 6];


a.forEach(function(ele, index,arr) {
     console.log(ele, index,arr);//輸出每個元素及對應的索引
})

//模擬源碼
Array.prototype.myForEach = function(func) {
    for (var i = 0; i < this.length; i++) {
        func(this[i], i);
    }
}
arr.myForEach(function(ele, index) {
    console.log(ele, index);
})

這裏寫圖片描述
這裏寫圖片描述

  • filter()方法(條件遍歷)

    • 根據邏輯條件返回調用數組子集,對數組元素進行篩選
    • 會跳過稀疏數組中缺少的元素。它的的返回數組總是稠密的。
var a = [5, 4, 3, 2, 1];
b = a.filter(function(ele) {
    return ele > 3 //篩選元素大於3的元素
});
console.log(b);
c = a.filter(function(ele, index) {
    return index % 2 == 0 //篩選索引爲偶數的元素
})
console.log(c);


var arr = [1, , 3, 4, , 6];
var newArr = arr.filter(function(ele, index) {
    return true;//壓縮稀疏數組空缺,返回稠密數組
    // return false;
})

var arr1 = arr.filter(function(ele, index) {
    if (ele > 3) {
        return true
    } else {
        return false
    }
})

這裏寫圖片描述
這裏寫圖片描述

這裏寫圖片描述

這裏寫圖片描述


數組排序

  • sort()方法(值轉換成->ASCII碼 | 傳參)
  • 參數是一個比較函數

  • 有關規則:大的、返回值1、置後 小的、返回值-1、置前

var arr = [100, 2, 0, 106, 7, 8];
arr.sort(); //(其實,在使用sort()進行排序的時候會調用toString()函數將其值轉換成字符串在進行比較,是按ASCII進行比較的)
console.log(arr);
arr.sort(function(first, last) {
    return first - last; //正序
    // return last - first; //倒序
    // return Math.random() - 0.5; //亂序
    // return -1;//ASC碼正序
    // return 1; //ASC碼倒序
});
console.log(arr);

var arr = [{name: 'tyx',search: 24005}, 
           {name: 'hx',search: 35637},
           {name: 'jj',search: 19800},
           {name: 'po',search: 59043}];
arr.sort(function(a, b) {
    return a.search - b.search;
})

這裏寫圖片描述
這裏寫圖片描述
這裏寫圖片描述
這裏寫圖片描述
這裏寫圖片描述
這裏寫圖片描述

var a = ['ant', 'Bug', 'cat', 'Dog'];
a.sort();
console.log(a);

a.sort(function(f, l) {
    var a = f.toLocaleLowerCase();
    var b = l.toLocaleLowerCase();
    if (a < b) return -1;
    if (a > b) return 1;
    return 0;
})
console.log(a);

這裏寫圖片描述

這裏寫圖片描述

  • reverse()方法(逆序排序)
var arr = [1, 2, 3, 4, 5, 6];
arr.reverse();//逆序排序
console.log(arr);
arr.sort(function(f, l) {
    return f - l
});
console.log(arr);
arr.sort(function(f, l) {
    return l - f
});
console.log(arr);

這裏寫圖片描述


數組方法

改變原數組的方法:

reverse() sort()

push() pop() unshift() shift() splice()

不改變原數組的方法:

join() concat() slice() toString()

map() reduce() every() some() filter()

indexOf() forEach()



  • join()

    將數組中所有元素連接在一起返回生成字符串,可以指定字符分割生成字符串

var a = ['a','b','c'];
a.join();
a.join(" ");
a.join("");
var b = new Array(10);
b.join("-");

這裏寫圖片描述


  • concat()

    合併數組,創建一個新數組 = 原數組 + 參數
    如果參數自身是數組,則連接數組中的元素
    concat()不會遞歸扁平化數組中的數組

var a = [1,2,3];
a.concat(4,5);//a[i] + 4,5
a.concat([4,5]);//連接數組元素
a.concat([4,5],[6,7]);
a.concat(4,[5,[6.7]]);//不會遞歸扁平化數組

這裏寫圖片描述

  • slice()(不改變原數組)

    返回指定數組的一部分
    含有兩個參數開始位置 結束位置不包含結束位置的參數
    若一個參數,表示從這個參數開始到結束
    若參數爲負值,表示相對於最後一個元素的位置
    -1表示最後一個元素

var a = [1,2,3,4,5];
a.slice(0,3);
a.slice(3);
a.slice(1,-1);
a.slice(-3,-2);//相當於(3,4)

這裏寫圖片描述


toString()和toLocaleString()

數組 -> 字符串

array.toString();  [return string]
  • 作用:將數組的每個元素 轉化爲字符串
  • 返回值:字符串

    • 相當於不使用任何參數調用 join()方法
    • 本地化版本,使用本地化分隔符連接
var a = [1, 2, 3, 4, 5, 'a', '8'];
console.log(a.toString());
console.log(a.join());

這裏寫圖片描述


map()

對數組每個元素加工

array.map(function(ele){
    return newArray;
})
  • 作用:將每個元素傳遞給指定函數,經過運算或加工
  • 參數:callback(currentValue) 操作函數
  • 返回值:一個新數組

    • 如果是稀疏數組,返回的也是對應的稀疏數組(相同長度和缺失元素)
var a = [1,2,3];
a.map(function(x){return x*x;})  // 1 4 9
["1","2","3"].map(parseInt);   //1,NaN,NaN

通常使用parseInt時,只需要傳遞一個參數。但實際上,parseInt可以有兩個參數,第二個參數是進制數,可以通過語句“alert(parseInt.length) === 2”來驗證。

  map()方法在調用callback函數時,會給它傳遞三個參數:當前正在遍歷的元素、元素索引、原數組本身。第三個參數parseInt會忽視,但第二個參數不會,也就是說,parseInt把傳過來的索引值當成進制數來使用,而parseInt的第二個參數的範圍爲2~36(不包含2但包含36),如果省略該參數或者其值爲0,則數字將以10爲基數來解析;如果小於2或者大於36,parseInt()將返回NaN,所以最終返回了[1,NaN,NaN]。

  實際上,這個小例子可以分解成這樣理解:

parseInt("1",0);  //基數爲0,以十進制來解析,返回1
parseInt("2",1)  //基數爲1,小於2,返回NaN
parseInt("3",2)  //基數爲2,小於2,返回NaN

every()和 some()

判斷數組元素是否全部或部分滿足一定條件

array.every(function(currentValue[元素值必須],index[可選],arr[可選]), thisValue)
array.every(function(ele){
    return boolean;
});
  • 作用:對數組元素邏輯判定,是否滿足一定條件
  • 參數:callback回調函數(數組元素值)
  • 返回值:布爾值
    • every()針對所有元素判定爲true,函數才返回true
    • some()至少含有一個元素判定爲true,函數返回true
    • 根據慣例,在空數組上調用,every()返回true,some()返回false
var a = [1, 2, 3, 4, 5];

a.every(function(ele) {
    return ele < 10  // true
})
a.every(function(ele) {
    return ele % 2 == 0 // false
})
a.some(function(ele) {
    return ele % 2 == 0; //是否存在一個元素被2整除
})    // true
a.some(isNaN); // 是否存在一個元素是非數字  false

reduce()和 reduceRight()

數組前後項做運算 返回累計值

array.reduce(function(ele){
    return result;
});
  • 作用:讓數組 前一項後一項 進行 某種運算,並 累計最終值
  • 兩個參數 :第一個是操作函數,用某種方法把兩個值化簡成一個值並返回。第二個是參數是傳給函數一個初始值(可選)
    • 當不傳第二個參數時,將使用數組的第一個元素作爲初始值
  • 返回值:操作函數執行後的累計值(一個運算結果)

    • 關於操作函數的參數有兩個:前一項和後一項
var a = [1, 2, 3, 4, 5];

a.reduce(function(x, y) {
    return x + y;  
    //reduce兩個參數:操作函數(兩個參數:前一項;後一項);初始值
}, 0)   //15

a.reduce(function(x, y) {
    return x * y  //數組求積
}, 1)    // 120

a.reduce(function(x, y) {
    return (x > y) ? x : y; //求最大值
})
       //5

indexOf()和 lastIndexOf()

匹配 給定值與數組元素

Array.indexOf (search, location)  [return index]
String.indexOf (search, location)
  • 作用:正向或逆向 根據給出值 匹配 數組 元素
  • 兩個參數搜索值搜索起始位置 (默認從頭開始 [0],負數表示相對於數組末位的偏移量)
  • 返回值第一個匹配元素的索引,或整個數組不匹配返回-1
var a = [0, 1, 2, 1, 0];
a.indexOf(1);   //  正向從頭搜索值1  返回值 1 表示索引
a.lastIndexOf(1); //  逆向從頭搜索值1  返回值3
a.indexOf(3);//  返回值-1

'btn mbtn'.indexOf('m');
  • 搜索指定的值,並返回包含所有匹配的數組索引的一個數組
function findAll(matchingArr, search) { // 匹配數組,搜索值
    var resultArr = [], //創建結果數組
        len = matchingArr.length, //記錄數組長度
        position = 0; //記錄檢索位置
    while (position < len) { // 索引對應,開始循環遍歷
        position = matchingArr.indexOf(search, position);
        //第一次匹配索引更新到position
        if (position === -1) break;
        resultArr.push(position); //將返回值壓入結果數組
        position = position + 1; //讓索引從下一位開始,此時pos並不是pos++,而是根據上面的方法返回值索引,下一次從該值繼續檢索
    }
    return resultArr;
}

var arr = ['a', 2, 'a', 'aa', 4, 'g', 7, 4, 5, 'a', 6, 9, 'a', 6, 4, 3, 'a', '7', 'a'];
findAll(arr, 'a');

這裏寫圖片描述


  • 比較各個函數

    這裏寫圖片描述
    這裏寫圖片描述
    這裏寫圖片描述


判斷數組類型

  • Array.isArray();
console.log(Array.isArray([]));
console.log(Array.isArray({}));

這裏寫圖片描述


數組特性

  • 當有新的元素添加到列表,會自動更新length
  • 設置length爲一個較小值會截斷數組
  • 從Array.prototype中繼承有用方法
  • 類屬性是‘Array’

類數組

  • 類數組[] 當一個對象中的屬性名是數字(類似數組索引),且有屬性length時,作類數組。 {2:,3:,length:2} = []
var obj = {
    2: 'a',
    3: 'b',
    push: Array.prototype.push,
    splice: Array.prototype.splice
};
console.log(obj);

這裏寫圖片描述

var obj = {
    2: 'a',
    3: 'b',
    length: 2,
    push: Array.prototype.push,
    splice: Array.prototype.splice
};
console.log(obj);

這裏寫圖片描述

  • 可以利用屬性名[索引]模擬數組的特性
  • 可以動態的增長length屬性
  • 如果強行讓類數組調用push方法,則會根據length屬性值的位置進行屬性的擴充
var obj = {
    2: 'a',
    3: 'b',
    length: 2,
    push: Array.prototype.push,
    splice: Array.prototype.splice
};

obj.push('c'); // obj[2] = 'a' <- 'c'  length++ 
console.log(obj);
obj.push('d'); // obj[3] = 'b' <- 'd'  length++
console.log(obj);

//涉及預編譯、push方法 實現源碼原理

var arr = [1, 2];
Array.prototype.myPush = function() {
   for (var i = 0; i < arguments.length; i++) {
       this[this.length] = arguments[i];
   }
   return this.length;
}
arr.myPush('a', 'b', 'c');
arr.myPush('d', 'e');

這裏寫圖片描述

  • 類數組對象沒有繼承自Array.prototype,而是Object.prototype那就不能在它們上面直接調用數組方法。但是可以間接的使用Function.call方法調用:
function roc(x){
    console.log(x);
}
var a = {'0':'a','1':'b','2':'c',length:3};
roc(a);
var b = Array.prototype.join.call(a,'+');
roc(b);
var c = Array.prototype.splice.call(a,1,0,'d');
roc(a);
roc(c);
var d = Array.prototype.map.call(a,function(x){
    return x.toUpperCase();
})
roc(d);

這裏寫圖片描述


作爲數組的字符串

  • ES5中,字符串的行爲類似只讀數組。
  • 可以用charAt()方法、[ ] 來訪問單個字符
var s = test;
s.charAt(0);
s[1];
  • 字符串的行爲類似於數組,通用的數組方法可以應用到字符串
  • 注意,字符串是不可變值,當作數組時它們是只讀的。
  • push,sort,reverse,splice修改字符串無效,導致錯誤,卻沒有提示
s = 'JavaScript';
Array.prototype.join.call(s,' ');
Array.prototype.filter.call(s,function(x){
    return x.match(/[^aeiou]/); //只匹配非元音字母
}).join(' ');

這裏寫圖片描述


數組去重

var arr = [10, 8, 9, 2, 8, 9, 10, 1, 2, 1, 2, 3, 9, 9, 10, 3, 5, 5];
Array.prototype.unique = function() {
    var memory = {};
    var newArr = [];
    for (var i = 0; i < this.length; i++) {
        if (!memory[this[i]]) {
            newArr.push(this[i]);
            memory[this[i]] = true;
        }
    }
    return newArr;
}

var newArr = arr.unique();
發佈了44 篇原創文章 · 獲贊 2 · 訪問量 5027
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章