数组的定义

数组是一个线性分配的内存, 存储的元素可以通过索引(通常为数字)来任意存取,而这个索引(也就是我们所谓的下标,从0开始)用来计算元素之间存储的位置的偏移量(其实就是为了区分不同的数据)。

js的数组和其它编程语言有些不同,表面上看和大多编程语言的数组差不多,但在内部却有着不一样的实现。js提供了一些类数组(array-like)特性的对象。它会把数组的下标转变成字符串,变成一个对象的属性。比如

var numbers = ['zero', 'one', 'two'];

这个简单的数组会被转换为

var numbers_object = {'0': 'zero', '1': 'one', '2': 'two'};

从代码本身的功能来说没有太大区别,刚好有相同的名字和值。但是numbers继承了Array.prototype,而numbers_object继承了Object.prototype。所以numbers就有了大量有用好玩的方法,还有一个特别的length属性。

js数组还有的一个特别之处是数组可以包含任何类型的数据,混合型的,很强大。

特别的length属性

  1. 每个数组都有一个length属性,length是没有上界的。如果用大于等于数组长度的数字作为下标来存储元素,那么length的值就会增大来容纳新元素,不会发生数组越界。

    var array = [10];
    var array[11] = 'iCoding';
    array.length //12

  2. 那么问题来了,js数组有没有下界。一般情况下数组都是从0开始的,如果执行array[-1] = 'net'会发生什么情况呢?数组的长度length会怎样变化?抱着刨根问题的精神回答,js数组会给array增加属性为-1的 '-1': 'net' 元素 ,其实本质就是上面所说的转换成对象,此时我们查询length的值并未发生变化,估计js源代码的length属性的值是从0开始计数的。

创建数组

  1. 最简单的方式

    var numbers = [ ]; //length = 0

  2. 直接放入一组元素

    var numbers = [1,2,3]; //length = 3

  3. 通过构造函数创建数组

    var numbers = new Array(); //length = 0

  4. 同样可以直接放入一组元素

    var numbers = new Array(1,2,3); //length = 3

那么那种方式最好?大多数javascript专家推荐使用[ ] 操作符,和使用构造函数相比,这种方式被认为效率最高。

数组操作

array[array.length] = 'iCoding';   --> ['zero', 'one', 'two', 'iCoding']

array.push('net');  --> ['zero', 'one', 'two', 'iCoding', 'net']

  1. 由于JavaScript的数组其实就是对象,所以delete运算符可以用来从数组中移除元素

    delete array[1]; --> ['zero', , 'two', 'iCoding', 'net']

但是这种方式会在数组中留下一空洞。因为排在后面的元素还会保留着它们最初的属性。

  1. JavaScript中有一个splice方法

    var array = ['zero', 'one', 'two', 'iCoding', 'net']

    array.splice(1, 1); -->['zero', 'two', 'iCoding', 'net']

其中splice第一个参数表示移除的位置,第二个参数表示移除元素的个数。

但是不好的一点是:被删除属性后面的每一个属性必须被移除,并且以一个新的键值重新插入,如果操作大型数组,效率可能就会不高。

  1. 如果想修改数组,依然可以用splice方法

    var array = ['a', 'b', 'c', 'd', 'e'];

    array.splice(3, 1, 'icoding', 'net'); -->['a', 'b', 'c', 'icoding', 'net', 'e'];

对数组的整体性操作

  1. 浅复制

当我们将一个数组赋给另外一个数组,只是为被赋值的数组增加了一个新的引用。当你通过原引用修改了数组的值,另一个引用也会感知到这个变化,相应的值就会发生改变。这种行为被称为浅复制。

var nums = [0, 1, 2, 3];
var same_nums = nums;
nums[1] = 99;
console.log(same_nums[1]); //99
  1. 深复制

顾名思义,也就是我们不同通过引用来改变另一个自己。写个函数就ok了。

function copy(arr1, arr2) {
for(var i = 0, i < arr1.length, i++) { 
arr2[i] = arr1[i]; 
  }
}

将每个数组中的值遍历出来在重新赋值到新数组中,在我们程序中调用一下就好了。

var nums = [0, 1, 2, 3];
var same_nums = []
copy(nums, same_nums);
nums[1] = 99;
console.log(same_nums[1]); //1

数组转化成字符串

这里有join()和toString()两个方法。

var names = ['joes', 'beyond'];

var namestr1 = names.join(); 

console.log(namestr);  //'joes,beyond'

var namestr2 = names.toString(); 

console.log(namestr);  //'joes,beyond'

由已有数组创建新数组

contact()和splice()方法允许通过已有数组创建数组。contact方法可以合并多个数组创建一个数组,splice()方法截取一个数组的子集创建一个新数组。

我们先来看看contact()方法的工作原理。随意创建2个数组。

var nums1 = [1, 2, 3, 4, 5];
var nums2 = [6, 7, 8, 9];
var mix_nums = nums1.contact(nums2);
console.log(mix_nums);  // [1, 2, 3, 4, 5, 6, 7, 8, 9]

参考

Michael McMillan.《Data Structures & Algorithms with JavaScript》
Douglas Crockford.《JavaScript: The Good Parts》


cnio
222 声望3 粉丝

个人网站:[链接]