(66)Wangdao.com第十一天_JavaScript 數組Array

數組 Array數組

本質上,數組屬於一種特殊的對象。typeof 運算符會返回數組的類型是 object函數

  • 數組的特殊性體如今,它的鍵名是按次序排列的一組整數(0,1,2...)
    // Object.keys方法返回數組的全部鍵名。
    
    var arr = ['a', 'b', 'c'];
    Object.keys(arr);    // ["0", "1", "2"]    // 能夠看到數組的鍵名就是整數0、一、2。
  • 數組的鍵名其實也是字符串。之因此能夠用數值讀取,是由於非字符串的鍵名會被轉爲字符串
  • JavaScript 使用一個32位整數,保存數組的元素個數。這意味着,數組成員最多隻有 4294967295 個(232 - 1)個,也就是說length屬性的最大值就是 4294967295

與普通對象的區別是 "數組使用數字做爲索引 [index] 來操做屬性"。index 從 0 開始。性能

數組的存儲性能相對較好。this

var arr = ['唐僧','孫悟空','豬八戒','沙和尚','白龍馬'];spa


 

1. 建立數組對象prototype

  • var arr = new Array();    // typeof arr    返回 object

2. 給數組添加對象code

  • arr[0] = 1;     // console.log(arr)    打印 "1"
    arr[1] = 11;    // console.log(arr)    打印 "1,11"
    arr[2] = 22;    // console.log(arr)    打印 "1,11,22"

3. 讀取數組對象對象

  • console.log(arr[0]);    // 1
    console.log(arr[1]);    // 11
    console.log(arr[2]);    // 22
    console.log(arr[3]);    // undefined    不會報錯

4. 獲取數組長度blog

  • arr.length 老是返回  "最大索引值+1" ,因此儘可能避免建立不連續數組
    var arr = [1,2,3];
    console.log(arr.length);    // 返回 3 ,由於有 3 個元素 arr[0],arr[1],arr[2]
    
    arr.[100] = 100;     // 此時數組有4個元素 arr[0],arr[1],arr[2],arr[100]
    console.log(arr.length);    // 可是會返回 101 , 實際只有 4 個元素, 這四個元素之外的其餘 97 個元素值都爲 undefined, 且用 in 判斷時返回 false
  • 清空數組的一個有效方法,就是將 arr.length屬性設爲 0
    var arr = [ 'a', 'b', 'c' ];
    
    arr.length = 0;
    arr    // []

     

  • b
  • b
  •  

5. 在數組最後添加元素排序

  • // 根據上一個特性,能夠在數組最後追加一個元素
    arr[arr.length] = 666;

     


 

1. 使用字面量來建立數組

  • var arr = [];    // 和 new Array() 效果相同

2. 在建立時指定元素

  • var arr = [0,1,2,3,4];
    
    // 等同於
    var arr = new Array(0,1,2,3,4);

3. 建立一個只有一個元素的數組

  • var arr = [10];    // 此時數組只有1個元素,arr[0] = 10;
    
    
    var arr = new Array(10);    // 此時建立了一個長度爲10的數組!!!
    // 每一個元素的值都爲 undefined

4. 數組中元素能夠聽任意數據類型的數據

  •  

    var arr = ["Hello","How",1,2,3,null,undefined,true,false];
    
    // 數組元素是對象
    var sun = {name:"孫悟空"};
    arr[arr.length] = sun;
    console.log(arr[arr.length-1].name);    // 將會打印 "孫悟空"
    
    
    // 數組元素是函數
    var arr = [
        function(){console.log("Hello!"},
        function(){console.log("Hi!")}
    ];
    
    // 數組 裏面放 數組
    var newArr = [["01","02","03"],[0,1,2],["11","22","33"]];
    
    // 混合着放
    var arr = [
      {a: 1},    // 對象
      [1, 2, 3],    // 數組
      function() {return true;}    // 函數
    ];
    
    arr[0]    // Object {a: 1}
    arr[1]    // [1, 2, 3]
    arr[2]    // function (){return true;}

     

5. 遍歷數組

  • for...in 循環不只能夠遍歷對象,也能夠遍歷數組,畢竟數組只是一種特殊對象
    var a = [1, 2, 3];
    
    for (var i in a) {
        console.log(a[i]);    // 1 2 3
    }

     

  • 可是,for...in不只會遍歷數組全部的數字鍵,還會遍歷非數字鍵。因此,不推薦使用 for...in 遍歷數組。
    var a = [1, 2, 3];
    a.foo = true;
    
    for (var key in a) {
        console.log(key);    // 0 1 2 foo
        console.log(key);    // 1 2 3 true
    }

     

  • 數組的遍歷能夠考慮使用 for循環 while循環
    var a = [1, 2, 3];
    
    // for循環
    for(var i = 0; i < a.length; i++) {
        console.log(a[i]);
    }
    
    // while循環
    var i = 0;
    while (i < a.length) {
        console.log(a[i]);
        i++;
    }
    
    // 逆向遍歷
    var l = a.length;
    while (l--) {
        console.log(a[l]);
    }

     

  • 數組的 arr.forEach() 方法,也能夠用來遍歷數組
    var colors = ['red', 'green', 'blue'];
    colors.forEach(function (color) {
        console.log(color);    // red green blue
    });

     

  • 數組的空位 hole        不影響length屬性
    • 當數組的某個位置是空元素,即兩個逗號之間沒有任何值,咱們稱該數組存在空位(hole)
    • 若是最後一個元素後面有逗號,並不會產生空位。也就是說,有沒有這個逗號,結果都是同樣的。
      var a = ['a' , , 'c'];
      a.length     // 3
      // 數組的空位是能夠讀取的,返回a[1] // undefined
      a[2] // 'c'

      undefined
      a[0] // 'a'
      a.length     // 3var a = [1, 2, 3,];
  • delete 命令刪除一個數組成員,會造成空位,而且不會影響length屬性
    var a = [1, 2, 3];
    delete a[1];
    
    a[1]    // undefined
    a.length    // 3

     

  • 數組的某個位置是空位,與某個位置是undefined,是不同的。
    • 若是是空位,使用數組的forEach方法、for...in結構、以及Object.keys方法進行遍歷,空位都會被跳過
      var a = [, , ,];
      
      a.forEach(function (x, i) {
          console.log(i + '. ' + x);    // 不產生任何輸出
      })
      
      for (var i in a) {
          console.log(i);    // 不產生任何輸出
      }
      
      Object.keys(a)    // []
    • 若是某個位置是 undefined,遍歷的時候就不會被跳過
      var a = [undefined, undefined, undefined];
      
      a.forEach(function (x, i) {
          console.log(i + '. ' + x);
      });
      // 0. undefined
      // 1. undefined
      // 2. undefined
      
      for (var i in a) {
          console.log(i);    // 0 1 2
      }
      
      Object.keys(a)    // ['0', '1', '2']

       

6. 相似數組對象

  • 若是一個對象的全部鍵名都是正整數或零,而且有length屬性,那麼這個對象就很像數組,語法上稱爲「相似數組的對象」(array-like object)。
    var obj = {
      0: 'a',
      1: 'b',
      2: 'c',
      length: 3
    };
    
    obj[0] // 'a'
    obj[1] // 'b'
    obj.length // 3
    obj.push('d')    // TypeError: obj.push is not a function
    // 由於它們不具有數組特有的方法。
    // 對象obj沒有數組的push方法,使用該方法就會報錯。

     

  • 有一個問題,這種length屬性不是動態值,不會隨着成員的變化而變化
  • 典型的「相似數組的對象」有 函數的arguments對象,以及大多數 DOM 元素集,還有字符串
  • 數組的slice方法能夠將 「相似數組的對象」 變成真正的數組
    • var arr = Array.prototype.slice.call(arrayLike);

       

  • 經過call(),能夠把 forEach() 嫁接到 arrayLike 上面調用
    • 如:在arguments對象上面調用forEach方法。
      // forEach 方法
      function logArgs() {
          Array.prototype.forEach.call(arguments, function (elem, i) {
              console.log(i + '. ' + elem);
          });
      }
      
      // 等同於 for 循環
      function logArgs() {
          for (var i = 0; i < arguments.length; i++) {
              console.log(i + '. ' + arguments[i]);
          }
      }

       

  • 注意,這種方法比直接使用數組原生的forEach要慢,
  • 因此最好仍是先將「相似數組的對象」轉爲真正的數組,而後再直接調用數組的forEach方法。
    var arr = Array.prototype.slice.call('abc');
    arr.forEach(function (chr) {
          console.log(chr);    // a b c
    });

     

7. 數組的靜態方法

  • Array.isArray()    判斷變量是不是數組
    var arr = [1, 2, 3];
    
    typeof arr // "object"
    Array.isArray(arr) // true

     

8. 數組的實例方法

  • .valueOf()    數組的 valueOf方法 返回數組自己。。。不一樣對象的valueOf方法不盡一致
  • .toString()    數組的toString方法 返回數組的字符串形式
  • .push()    用於在數組的末端添加一個或多個元素,並返回添加新元素後的數組長度。注意,該方法會改變原數組
    • var arr = [];
      
      arr.push(1);    // 1
      arr.push('a');    // 2
      arr.push(true, {});    // 4
      
      // arr = [1, 'a', true, {}]

       

  • .pop()    用於刪除數組的最後一個元素,並返回該元素。注意,該方法會改變原數組
    • var arr = ['a', 'b', 'c'];
      
      arr.pop()    // 'c'
      
      // arr = ['a', 'b']

      對空數組使用pop方法,不會報錯,而是返回undefined

    • pushpop結合使用,就構成了「後進先出」的棧結構(stack)

 

  • .shift()    用於刪除數組的第一個元素,並返回該元素。注意,該方法會改變原數組
    • shift方法能夠遍歷並清空一個數組。
      var list = [1, 2, 3, 4, 5, 6];
      var item;
      
      while (item = list.shift()) {
          console.log(item);
      }
      
      list     // []
    • pushshift結合使用,就構成了「先進先出」的隊列結構(queue)

 

  • .unshift()    用於在數組的第一個位置添加元素,並返回添加新元素後的數組長度。注意,該方法會改變原數組
    • unshift方法能夠接受多個參數,這些參數都會添加到目標數組頭部

 

  • .join()    以指定參數做爲分隔符,將全部數組成員鏈接爲一個字符串返回。若是不提供參數,默認用逗號分隔。
    • var a = [1, 2, 3, 4];
      
      a.join(' ');    // '1 2 3 4'
      a.join(' | ');    // "1 | 2 | 3 | 4"
      a.join();    // "1,2,3,4"
      [undefined, null].join('#') // '#' ['a',, 'b'].join('-') // 'a--b'

      若是數組成員是undefinednull或空位,會被轉成空字符串

    • 經過call方法,這個方法也能夠用於字符串或相似數組的對象
      Array.prototype.join.call('hello', '-')    // "h-e-l-l-o"
      
      var obj = { 0: 'a', 1: 'b', length: 2 };
      Array.prototype.join.call(obj, '-')    // 'a-b'

       

  • .concat()    用於多個數組的合併。
    • 它將新數組的成員,添加到原數組成員的後部,而後返回一個新數組,原數組不變
    • ['hello'].concat(['world']);    // ["hello", "world"]
      
      ['hello'].concat(['world'], ['!']);    // ["hello", "world", "!"]
      
      [].concat({a: 1}, {b: 2});    // [{ a: 1 }, { b: 2 }]
      
      [2].concat({a: 1});    // [2, {a: 1}]

       

    • 若是數組成員包括對象,concat方法返回當前數組的一個淺拷貝。所謂「淺拷貝」,指的是新數組拷貝的是對象的引用
      • 改變原對象之後,新數組跟着改變

 

  • .reverse()    顛倒排列數組元素,返回改變後的數組。注意,該方法將改變原數組

 

  • .slice(start, end)    用於提取目標數組的一部分,返回一個新數組,原數組不變
    • 它的第一個參數爲起始位置(從0開始),
    • 第二個參數爲終止位置(但該位置的元素自己不包括在內)。若是省略第二個參數,則一直返回到原數組的最後一個成員
    • 若是slice方法的參數是負數,則表示倒數計算的位置
    • 若是第一個參數大於等於數組長度,或者第二個參數小於第一個參數,則返回空數組。
    • var a = ['a', 'b', 'c'];
      a.slice(-2);    // ["b", "c"]
      a.slice(-2, -1);    // ["b"]
      
      var a = ['a', 'b', 'c'];
      a.slice(4);    // []
      a.slice(2, 1);    // []

       

    • Array.prototype.slice().call()方法的一個重要應用,是 將相似數組的對象轉爲真正的數組
      Array.prototype.slice.call({ 0: 'a', 1: 'b', length: 2 })    // ['a', 'b']
      
      Array.prototype.slice.call(document.querySelectorAll("div"));
      Array.prototype.slice.call(arguments);

       

  • .splice(start, count, addElement1, addElement2, ...)    
    • 用於刪除原數組的一部分紅員,並能夠在刪除的位置添加新的數組成員,返回值是被刪除的元素。注意,該方法會改變原數組
    • 第一個參數是刪除的起始位置(從0開始),起始位置若是是負數,就表示從倒數位置開始刪除。
    • 第二個參數是被刪除的元素個數,
    • 若是後面還有更多的參數,則表示這些就是要被插入數組的新元素。
    • 若是隻提供第一個參數,從起始位置開始,刪除後面全部元素組成一個數組返回

 

  • .sort()    對數組成員進行排序,默認是按照字典順序排序。排序後,原數組將被改變
    • 數值會被先轉成字符串,再按照字典順序進行比較因此101排在11的前面
    • 若是想讓sort方法按照自定義方式排序,能夠傳入一個函數做爲參數
      • 函數自己接受兩個參數,表示進行比較的兩個數組成員。若是該函數的返回值大於0,表示第一個成員排在第二個成員後面;其餘狀況下,都是第一個元素排在第二個元素前面。
        [10111, 1101, 111].sort(function (a, b) {
            return a - b;
        });    // [111, 1101, 10111]
        [
            { name: "張三", age: 30 },
            { name: "李四", age: 24 },
            { name: "王五", age: 28  }
        ].sort(function (o1, o2) {
            return o1.age - o2.age;
        });
        
        // [
        //     { name: "李四", age: 24 },
        //     { name: "王五", age: 28  },
        //     { name: "張三", age: 30 }
        // ]

         

  • .map()    方法
    • 將數組的全部成員依次傳入參數函數,
    • 而後把每一次的執行結果組成一個新數組返回。。。原數組沒有變化
      • var numbers = [1, 2, 3];
        
        numbers.map(function (n) {
            return n + 1;
        });    // [2, 3, 4]
        
        numbers    // [1, 2, 3]

         

    • 該函數調用時,map方法向它傳入三個參數:當前成員 elem、當前位置 index數組自己 arr
      • [1, 2, 3].map(function(elem, index, arr) {
          return elem * index;
        });    // [0, 2, 6]

         

    • map方法還能夠接受第二個參數,用來綁定回調函數內部的this變量
      • var arr = ['a', 'b', 'c'];
        
        [1, 2].map(function (e) {
            return this[e];
        }, arr)    // ['b', 'c']

         

    • 若是數組有空位,map方法的回調函數在這個位置不會執行,會跳過數組的空位 (不會跳過不會跳過undefinednull)
      • var f = function (n) { return 'a' };
        
        [1, undefined, 2].map(f);    // ["a", "a", "a"]
        [1, null, 2].map(f);    // ["a", "a", "a"]
        [1, , 2].map(f);    // ["a", , "a"]

         

  • .forEach()    
    • map方法很類似,也是對數組的全部成員依次執行參數函數
    • 可是,forEach方法不返回值,只用來操做數據。
    • 這就是說,若是數組遍歷的目的是爲了獲得返回值,那麼使用map方法,不然使用forEach方法
    • 參數是一個函數,該函數一樣接受三個參數:當前成員 elem、當前位置 index數組自己 arr
    • forEach方法也能夠接受第二個參數,綁定參數函數的 this 變量
    • forEach方法也會跳過數組的空位 , 不會跳過undefinednull
    • var out = [];
      
      [1, 2, 3].forEach(function(elem) {
         this.push(elem * elem);
      }, out);
      
      out    // [1, 4, 9]

       

    • 注意 : 
      • forEach方法沒法中斷執行,老是會將全部成員遍歷完。
      • 若是但願符合某種條件時,就中斷遍歷,要使用for循環

 

  • .filter()    用於過濾數組成員,知足條件的成員組成一個新數組返回
    • 參數是一個函數,全部數組成員依次執行該函數,返回結果爲true的成員組成一個新數組返回。該方法不會改變原數組。
      • [1, 2, 3, 4, 5].filter(function (elem) {
            return (elem > 3);
        });    // [4, 5]    將大於3的數組成員,做爲一個新數組返回
        
        
        var arr = [0, 1, 'a', false];
        
        arr.filter(Boolean);    // [1, "a"]    獲取全部布爾值爲true的成員

         

    • 函數能夠接受三個參數:當前成員 elem、當前位置 index數組自己 arr
      • [1, 2, 3, 4, 5].filter(function (elem, index, arr) {
            return index % 2 === 0;
        });    // [1, 3, 5]

         

    • filter方法還能夠接受第二個參數,用來綁定參數函數內部的this變量
      • var obj = { MAX: 3 };
        var myFilter = function (item) {
            if (item > this.MAX) return true;
        };
        
        var arr = [2, 8, 3, 4, 1, 3, 2, 9];
        arr.filter(myFilter, obj);    // [8, 4, 9]

         

  • .some() 和 every()
      • 這兩個方法相似「斷言」(assert),返回一個布爾值,表示判斷數組成員是否符合某種條件
      • 接受一個函數做爲參數,全部數組成員依次執行該函數。而後返回一個布爾值
      • 該函數接受三個參數:當前成員 elem、當前位置 index數組自己 arr
    • some方法是隻要一個成員的返回值是true,則整個some方法的返回值就是true,不然返回false
      • var arr = [1, 2, 3, 4, 5];
        arr.some(function (elem, index, arr) {
            return elem >= 3;
        });    // true

         

    • every方法是全部成員的返回值都是true,整個every方法才返回true,不然返回false
      • var arr = [1, 2, 3, 4, 5];
        arr.every(function (elem, index, arr) {
            return elem >= 3;
        });    // false

         

    • 注意,對於空數組,some方法返回falseevery方法返回true,回調函數都不會執行

 

  • .reduce()  和  .reduceRight()  
    • 依次處理數組的每一個成員,最終累計爲一個值。
    • 它們的差異是 : 
      • reduce是從左到右處理(從第一個成員到最後一個成員)
      • reduceRight則是從右到左(從最後一個成員到第一個成員),其餘徹底同樣
    • // 求出數組全部成員的和
      [1, 2, 3, 4, 5].reduce(function (a, b) { console.log(a, b); return a + b; }); // 1 2 第一次執行, 是數組的第一個成員,是數組的第二個成員 // 3 3 第二次執行, 爲上一輪的返回值,爲第三個成員 // 6 4 第三次執行, 爲上一輪的返回值,爲第四個成員 // 10 5 第四次執行, 爲上一輪返回值,爲第五個成員 // 最後結果:15a1b2a3b3a6b4a10b5

       

    • reduce() 和 reduceRight() 的第一個參數都是一個函數。該函數接受如下四個參數
      • 累積變量,默認爲數組的第一個成員
      • 當前變量,默認爲數組的第二個成員
      • 當前位置(默認從0開始)
      • 原數組
      • 只有前兩個是必須的,後兩個則是可選的
    • 若是要對累積變量指定初值,能夠把它放在reduce方法和reduceRight方法的第二個參數
      • [1, 2, 3, 4, 5].reduce(function (a, b) {
            return a + b;
        }, 10);    // 25 // 指定參數a的初值爲10,因此數組從10開始累加,最終結果爲25。 // 注意,這時b是從數組的第一個成員開始遍歷

         

    • 因爲空數組取不到初始值,reduce方法會報錯。這時,加上第二個參數,就能保證老是會返回一個值
    • function substract(prev, cur) {
          return prev - cur;
      }
      // 比較 reduce() reduceRight()
      [3, 2, 1].reduce(substract) // 0
      [3, 2, 1].reduceRight(substract) // -4

       

    • 還能夠用來作一些遍歷相關的操做。好比,找出字符長度最長的數組成員
      • function findLongest(entries) {
            return entries.reduce(function (longest, entry) {
                return entry.length > longest.length ? entry : longest;
            }, '');
        }
        
        findLongest(['aaa', 'bb', 'c']);     // "aaa"

         

  • .indexOf()    返回給定元素在數組中第一次出現的位置,若是沒有出現則返回-1
    • 還能夠接受第二個參數,表示搜索的開始位置
      var a = ['a', 'b', 'c'];
      
      a.indexOf('b');    // 1
      a.indexOf('y');    // -1
      
      ['a', 'b', 'c'].indexOf('a', 1);    // -1    結果爲-1,表示沒有搜索到

       

  • .lastIndexOf()    返回給定元素在數組中最後一次出現的位置,若是沒有出現則返回-1
    • var a = [2, 5, 9, 2];
      a.lastIndexOf(2);    // 3

      a.lastIndexOf(7); // -1
      [NaN].indexOf(NaN) // -1
      [NaN].lastIndexOf(NaN) // -1

       

    • 不能用來搜索NaN的位置,即它們沒法肯定數組成員是否包含NaN

 

  • 有很多返回的仍是數組,因此能夠鏈式使用
    • var users = [
          {name: 'tom', email: 'tom@example.com'},
          {name: 'peter', email: 'peter@example.com'}
      ];
      
      users
      .map(function (user) {
          return user.email;
      })
      .filter(function (email) {
          return /^t/.test(email);
      })
      .forEach(function (email) {
          console.log(email);
      });
      // 先產生一個全部 Email 地址組成的數組,而後再過濾出以t開頭的 Email 地址,最後將它打印出來
相關文章
相關標籤/搜索