JavaScript中的數組建立

JavaScript中的數組建立

數組是一個包含了對象或原始類型的有序集合。很難想象一個不使用數組的程序會是什麼樣。javascript

如下是幾種操做數組的方式:java

  1. 初始化數組並設置初始值web

  2. 經過索引訪問數組元素數組

  3. 添加新元素瀏覽器

  4. 刪除現有元素函數

本文涵蓋了數組的初始化以及設置初始值的操做。在JavaScript中要作到這一點的基本方法是使用數組字面量,例如[1, 5, 8]或是數組構造器new Array (1, 5, 8)prototype

除了手動枚舉以外,JavaScript還提供了更有趣更直接的數組建立方式。讓我一塊兒看看在JavaScript中初始化數組的通常場景和高級場景吧。翻譯

1. 數組字面量

數組字面量由一組包裹在方括號[ ]之間的逗號分隔的元素element1, element2, ..., elementN組成。code

讓咱們看幾個數組字面量的例子:對象

在JS Bin中查看

let numbers = [1, 5, 7, 8];
let planets = ['Earth', 'Mercury', 'Jupiter'];

數組字面量能夠包含任意類型的元素,包括null, undefined, 原始類型以及對象:

在JS Bin中查看

let mixed = [1, 'Earth', null, NaN, undefined, ['Mars']];

1.1 數組字面量中的逗號

逗號,用來分隔數組字面量中的元素。基於逗號的位置或是逗號之間元素的缺失的狀況,不一樣結構的數組會被建立。

讓咱們詳細看一看現有的三種狀況。

第一種狀況:普通的數組字面量

一般狀況是在任何一對逗號之間都有一個元素而且數組字面量不以逗號開始或結尾。這是推薦的使用逗號分隔手動初始化數組的方式:

在JS Bin中查看

let items = ['first', 'second', 'third'];
items; // => ['first', 'second', 'third']

items是由2個逗號分隔的3個元素建立的。

在這個例子中item是一個密集數組,由於它的元素有着連續的索引(或者簡單來講數組中沒有空洞)。

大多數時候,你會使用這種方式初始化數組。

第二種狀況: 在數組末尾的一個無用逗號

第二種狀況和第一種狀況相似,只不過在最後一個逗號以後沒有指定元素。這種狀況中,最後一個逗號會被JavaScript忽略:

在JS Bin中查看

let items = ['first', 'second', 'third', ];
items; // => ['first', 'second', 'third']

在元素'third'以後指定的一個逗號,它是數組中的最後一個逗號而且在那以後沒有任何元素。這個末尾的逗號是無用的,意味着它對新建立的數組沒有任何影響。

這種狀況下JavaScript也會建立一個密集數組。

第三種狀況: 逗號之間沒有元素

第三種狀況發生在當一對逗號之間沒有指定元素或是數組字面量以一個逗號開始時。

這會建立一個稀疏數組:一個其元素索引不連續的集合(換句話說數組中存在空洞)。

下面的數組字面量以逗號開始,建立了一個稀疏數組:

在JS Bin中查看

let items = [, 'first', 'second', 'third'];
items;        // => [<1 empty slot>, 'first', 'second', 'third']
items[0];     // => undefined
items[1];     // => 'first'
items.length; // => 4

數組字面量[, ...]以逗號開始。結果是items是一個稀疏數組,在索引0的位置是一個空slot。訪問空slot items[0]會獲得undefined

區分一個空slot和一個值是undefined的元素是很重要的。經過索引訪問這種類型的元素時都會獲得undefined,這使得區分它們變得很棘手。

空slot意味着數組在某個索引位置上沒有元素(index in array返回false),這與一個值是undefined的元素(index in array返回true)是不一樣的。

須要注意的是空slot在Firefox的控制檯會被顯示爲<1 empty slot>,這是展現空slot的正確方法。Chrome的控制檯會展現undefined x 1。其它瀏覽器的控制檯只會簡單的展現undefined

當數組字面量的兩個逗號之間沒有元素時也會建立一個稀疏數組:

在JS Bin中查看

let items = ['first', , 'second', 'third'];
items;        // => ['first', <1 empty slot> ,'second', 'third']
items[0];     // => 'first'
items[1];     // => undefined
items.length; // => 4

數組字面量包含了中間沒有元素的逗號:[... , , ...]。這樣item成了一個索引1處是一個空slot的稀疏數組。訪問空slot items[1]會獲得undefined

一般你應該避免這種會建立稀疏數組的使用方式。同時你也應該儘量的不去操做稀疏數組。

在一個數組字面量中刪除或是添加元素時你可能會在不經意間建立一個稀疏數組。所以在修改以後切記仔細檢查。

1.2 spread運算符帶來的改善

ECMAScript 6中引入的spread運算符改善了使用其它數組中的元素初始新數組這一操做。

在不少場景下spread運算符均可以使數組建立變得更簡單。方法就是在數組字面量中把...做爲源數組的前綴,而後源數組中的元素就被包括到新建立的數組中了。就這麼簡單。

下面的數組字面量在建立時使用了spread運算符:

在JS Bin中查看

let source = ['second', 'third'];
let items = ['first', ...source];
items; // => ['first', 'second', 'third']

數組字面量['First', ...source]表示'First'會被做爲數組中的第一個元素。剩餘的元素則是經過spread運算符從source數組取得。

常規的元素枚舉方式能夠和spread運算符能夠不受限制的組合在一塊兒。

在JS Bin中查看

let odds = [1, 3, 5];
let evens = [4, 6];
let zero = 0;
let negative = -1;
let items = [...odds, zero, ...evens, negative];
items; // => [1, 3, 5, 0, 4, 6, -1]

建立items時使用一個組合了普通變量zeronegative以及前置spread運算符的源數組...odds...evens的集合。

因爲spread運算符接收的是普通的可迭代對象(數組默認就是可迭代的),這使得自定義的初始化成爲可能。

一個生成器函數也會返回一個可迭代的生成器對象,所以你能夠利用生成器的靈活性來建立數組。

讓咱們建立一個第一個參數表明元素值第二個參數表明元素數量的生成器函數。而後使用它和spread運算符以及數組字面量來初始化新數組:

在JS Bin中查看

function* elements(element, length) {
  let index = 0;
  while (length > index++) {
    yield element;
  }
}
[...elements(0, 5)];    // => [0, 0, 0, 0, 0]
[...elements('hi', 2)]; // => ['hi', 'hi']

每次執行elements(element, length)時都會建立一個生成器對象。spread運算符會利用該生成器對象來初始化數組。

[...elements(0, 5)]會建立一個有5個0的數組。而[...elements('hi', 2)]會建立一個有兩個字符串'h1'的數組。

2. 數組構造器

JavaScript中的數組是一個對象。和任何對象同樣,它有一個能夠用來建立新實例的構造器函數Array。讓咱們看一個例子:

在JS Bin中查看

// 構造器調用
let arrayConstr = new Array(1, 5);
arrayConstr;                        // => [1, 5]
typeof arrayConstr;                 // => 'object'
arrayConstr.constructor === Array;  // => true
// 數組字面量
let arrayLiteral = [1, 5];
arrayLiteral;                       // => [1, 5]
typeof arrayLiteral;                // => 'object'
arrayLiteral.constructor === Array; // => true

arrayConstrarrayLiteral都是數組實例,它們的構造器都是Array。對象arrayConstr是經過構造器調用建立的:new Array(1, 5)

你也能夠像調用普通函數那樣經過Array來建立數組實例:Array(1, 5)

你應該更傾向於使用字面量[item1, item2, ..., itemN]而不是構造器new Array(item1, item2, ..., itemN)來建立數組。主要緣由是數組字面量的寫法更短,更簡單。還有一個緣由就是數組構造器在第一個參數是不一樣類型的值時,產生的怪異行爲。

讓咱們看看Array使如何根據第一個參數的類型以及參數的個數來建立數組實例的吧。

2.1 數值類型的參數下建立稀疏數組

當數組構造器new Array(numberArg)以一個單一的數值類型的參數調用時,JavaScript會建立一個帶有參數指定的個數的空slot的稀疏數組。

看一個例子:

在JS Bin中查看

let items = new Array(3);
items;        // => [<3 empty slots>]
items.length; // => 3

new Array(3)是一個帶有單一參數3的構造器調用。一個長度爲3的稀疏數組items被建立了,但實際上它並不包含任何元素而只是有幾個空slot。

這種建立數組的方式自己並無什麼價值。然而把它和一些靜態方法組合起來用於建立指定長度的數組並填充生成的元素時倒是有用的。

2.2 枚舉元素

若是調用Array構造器時傳入了一個參數列表而不是單個數字,那麼這些參數就會成爲數組的元素。

這種方式和數組字面量的方式幾乎同樣,只不過是在一個構造器調用中而已。

下面的例子建立了一個數組:

let items = new Array('first', 'second', 'third');
items; // => ['first', 'second', 'third']

new Array('first', 'second', 'third')使用參數中的元素建立了一個數組。

因爲spread運算符的靈活性,在構造器調用中使用來自其它數組的元素也是可行的:

在JS Bin中查看

let source = new Array('second', 'third');
let items = new Array('first', ...source);
items; // => ['first', 'second', 'third']

new Array('First', ...source)建立數組時使用了'First'元素以及source數組中的全部元素。

不管哪一種方式,你都應該傾向於使用數組字面量,由於它更簡單直接。

2.3 有用的靜態方法

當讀到關於經過在構造器調用中傳入一個數字來建立稀疏數組的部分時你可能好奇這有什麼實際的用處。

ECMAScript 6增長了一些有用的方法如Array.prototype.fill()Array.from()。這兩個方法均可以用來填充一個稀疏數組中的空slot。

讓我使用fill()方法來建立一個包含5個0的數組:

在JS Bin中查看

let zeros = new Array(5).fill(0);
zeros; // => [0, 0, 0, 0, 0]

new Array(5)建立了一個有5個空slot的稀疏數組。接着fill(0)方法用0填充了空slot。

靜態方法Array.from()則有着更寬的使用場景。像上邊的例子同樣,讓咱們建立一個包含5個0的數組:

在JS Bin中查看

let zeros = Array.from(new Array(5), () => 0);
zeros; // => [0, 0, 0, 0, 0]

一個經過new Array(5)建立的長度爲5的稀疏組數做爲參數被傳遞給Array.from()。第二個參數做爲一個返回0的映射函數。

共執行了5次迭代,每次迭代中箭頭函數的返回值被用做數組的元素。

因爲在每次迭代中都會執行映射函數,所以動態建立數組元素是可行的。讓咱們建立一個包含15的數組:

在JS Bin中查看

let items = Array.from(new Array(5), (item, index) => index + 1);
items; // => [1, 2, 3, 4, 5]

映射函數被調用時會傳入兩個參數:當前的item以及當前迭代的index。索引參數被用來生成元素:index + 1

Array.from()的第一個參數能夠接受任何可迭代對象,這使得它更有價值。

讓咱們使用一個生成器對象建立一個遞增的數字列表:

在JS Bin中查看

function* generate(max) {
  let count = 0;
  while (max > count++) {
    yield count;
  }
}
let items = Array.from(generate(5));
items;       // => [1, 2, 3, 4, 5]
let itemsSpread = [...generate(5)];
itemsSpread; // => [1, 2, 3, 4, 5]

generate(max)是一個生成器函數,它會生成從一串從1max的數字。

Array.from(generate(5))使用一個生成器對象做爲參數建立了一個包含15數字的數組。

使用spread運算符[...generate(5)]和數組字面量能夠達到一樣的目的。

3. 總結

數組初始化是操做集合時的常見操做。JavaScript提供了多種方法以及靈活性來實現該目的。

數組構造器的行爲在不少狀況下會讓你感到意外。所以數組字面量是初始化數組實例更好,更簡單的方式。

當數組須要根據基於每一個迭代元素的計算進行初始化時,Array.from()是一個不錯的選擇。

若是數組元素須要被填充爲同一個值,使用Array.prototype.fill()new Array(length)的組合。

不要低估可迭代對象和生成器函數的能力,它們能夠和spread運算符組合起來使用在數組字面量或是Array.from()中。

本文轉載自:衆成翻譯
譯者:loveky
連接:http://www.zcfy.cc/article/713
原文:http://rainsoft.io/power-up-the-array-creation-in-javascript/

相關文章
相關標籤/搜索