[JS] 陣列

此文章摘錄自’JavaScript優良部分’一書,純粹個人備忘之用。如欲看全文,請參閱該書。

陣列實字

// 陣列實字
var empty = [];
var numbers = [
  'zero', 'one', 'two', 'three', 'four',
  'five', 'six', 'seven', 'eight', 'nine'
];

empty[1];   // undefined
numbers[1]; // 'one'

//物件實字
var numbers_object = {
  '0': 'zero' , '1': 'one'  , '2': 'two',
  '3': 'three', '4': 'four' , '5': 'five',
  '6': 'six'  , '7': 'seven', '8': 'eight',
  '9': 'nine'
};

以上numbers與number_object都是包含十項特性的物件,這些特性也具有完全相同的名稱與值;但numbers繼承自Array.prototype,而number_object卻繼承自Object.prototype;所以,numbers繼承了較多有用的方法。還有numbers也具有length特性,這是number_object所沒有的特性。

在多數語言中,陣列元素都必須為相同型別。JavaScript則允許陣列包含各種型別混合的值:

var misc = [
  'string', 98.6, true, false, null, undefined,
  ['nested', 'array'], {object: true}, NaN,
  Infinity
];

misc.length  // 10

length特性

每個陣列都有一個length特性。是陣列中最大的整數特性名稱加1

var myArray = [];
myArray.length  // 0

myArray[1000000] = true;
myArray.length  // 1000001
// myArray只包含一個特性

// 假設numbers現在改成['zero', 'one', 'two']
numbers.length = 3;

// 新的陣列元素,可藉由指派給陣列目前的length而被附加至陣列尾端:
numbers[numbers.length] = 'shi';
// numbers成為['zero', 'one', 'two', 'shi']

// 有時候,使用push方法更易於達成相同效果:
numbers.push('go');
// numbers成為['zero', 'one', 'two', 'shi', 'go']

刪除

// numbers目前是['zero', 'one', 'two', 'shi', 'go']

delete numbers[2];
// number成為['zero', 'one', undefined, 'shi', 'go']
// 但通常我們會想把右側每個元素的名稱同步減1,所以最好改成以下:
numbers.splice(2, 1);
// number成為['zero', 'one', 'shi', 'go']

splice方法,它可以對陣列動手術,刪除某些元素,並以其它元素代替。第一個引數是陣列裡的序號;第二個引數是欲刪除的元素數量。任何附加的引數,都將被插入陣列中。

列舉

var i;
for(i = 0; i < myArray.length; i += 1){
  document.writeln(myArray[i]);
}

困惑之處

JavaScript程式的常見錯誤之一,是在該用陣列時用了物件,或是該用物件時用了陣列。規則很簡單:當特性名稱是連續小整數時,就應該用陣列;否則應該用物件。

JavaScript對於陣列與物件的差別,其實也搞不太清礎。typeof運算子回報的陣列型別是’object’,更是大幫倒忙。

JavaScript沒有很好的陣列與物件區分機制。所以我們必須自訂is_array函式,可繞過這項缺陷:

var is_array = function(value){
  return value &&
         typeof value === 'object' &&
         typeof value.length === 'number' &&
         typeof value.splice === 'function'  &&
         !(value.propertyIsEnumerable('length'));
};

方法

JavaScript提供一組對陣列行動的方法。這些方法就是儲存在Array.prototype裡的函式,假設要新增一個array方法至Array.prototype來擴充:

Array.method('reduce', function(f, value){
  var i;
  for(i = 0; i < this.length; i += 1){
    value = f(this[i], value);
  }
  return value;
});

//建立一個數值陣列
var data = [4, 8, 15, 16, 23, 42];

//建立兩個簡易函式。其中一個相加兩個數字;另一個相乘兩個數字
var add = function(a, b){
  return a + b;
};

var mult = function(a, b){
  return a * b;
};

// 呼叫資料的reduce方法,傳給add函式
var sum = data.reduce(add, 0);  // sum為108

// 再度呼叫reduce方法,這次傳入mult函式
var product = data.reduce(mult, 1);  // 乘積為7418880