作者:gcbeen

日期:2013年10月24日

一、Javascript数组

Javascript数组是无类型的:数组元素可以是任意类型,同一个数组中的不同元素可能有不同的类型,数组的元素可能是对象或其他数组。数组的实现是经过优化的,用数字索引来访问数组一般来说比访问常规对象属性要快很多。

数组继承自Array.prototype中的属性。

二、创建数组

数组直接量。

    var empty = [];
    var primes = [2, 3, 5, 7, 11];
    var misc = [1.1, true, "a", ];
    
    var base = 1024;
    var table = [base, base + 1, base + 2, base + 3];
    
    var b = [[1, {x: 1, y: 2}], [2, {x: 3, y: 4}]];
    
    var count = [1, ,3];
    var undefs = [,,] // 2个undefined元素

调用构造函数Array()创建数组。

    var a = new Array();
    var a = new Array(10);
    var a = new Array(5, 4, 3, 2, 1, "testing, testing");

三、数组元素的读和写

    var a = ["world"];
    var value = a[0];
    a[1] = 3.14;
    i = 2;
    a[i] = 3;
    a[i + 1] = "hello";
    a[a[i]] = a[0];

数组是对象的特殊形式。使用方括号访问数组元素就像用方括号访问对象的属性一样。Javascript将指定的数字索引值转换成字符串(索引值1变成“1”)然后将其作为属性名来使用。

索引值从数字转换为字符串,常规对象也会这么做。

    var o = {};
    o[1] = "one";
    a[-1.23] = true; //这将创建一个名为“-1.23”的属性
    a["1000"] = 0;   //数组的第1001个元素
    a[1.000]         //和a[1]相等

数组索引仅仅是对象属性名的一种特殊类型,Javascript数组没有“越界”错误的概念。当试图查询任何对象中不存在的属性时,不会报错,只会得到undefined值。类似于对象。

四、稀疏数组

稀疏数组是包含从0开始不连续索引的数组。通常,数组的length属性值代表数组中元素的个数。如果数组是稀疏的,length属性值大于元素的个数。

    var a = new Array(5);
    var a = [];
    a[1000] = 0;

当在数组直接量中省略值时不会创建稀疏数组。省略的元素是undefined。

    var a1 = [,,,];
    var a2 = new Array(3);
    0 in a1                 // true
    0 in a2                 // false
    var a1 = [,];
    var a2 = [undefined];
    0 in a1;
    0 in a2;

五、数组长度

length属性代表元素的个数或者最大索引值加1。

    [].length;
    ['a', 'b', 'c'].length;
    a = [1, 2, 3, 4, 5];
    a.length = 3;
    a.length = 0;
    a.length = 5;
    a = [1, 2, 3];
    Object.defineProperty(a, "length", {writable: false});
    a.length = 0;     // a不会改变

六、数组元素的添加和删除

    var a = [];
    a[0] = "zero";
    a[1] = "one";

    var a = [];
    a.push("zero");
    a.push("one", "two"); // ["zero", "one", "two"]
    a.unshift("-one");    // ["-one", "zero", "one", "two"]
    var a = [1, 2, 3];
    delete a[1];
    1 in a               // false:数组索引1并未在数组中定义
    a.length             // 3:delete操作不影响数组长度
    var a = [1, 2, 3]
    a.push(4);
    a.pop();          // 4
    a.unshift(-1);
    a.shift();        // -1
    
    a.splice();

七、数组遍历

for循环

    var keys = Object.keys(o);  // 获得o对象属性名组成的数组
    var values = [];
    var i,
        len = keys.length;
    for (i = 0; i < len; i += 1) {
      if (!a[i]) {
        continue;
      }
      var key = keys[i];
      values[i] = o[key];
    }

for/in循环处理稀疏数组

var index,
    value;
for (index in sparseArray) {
  if (!a.hasOwnProperty(i) ) {
    continue;
  }
  value = sparseArray[index]
}

for (index in sparseArray) {
  if (String(Math.floor(Math.abs(Number(i) ) ) ) === i ) {
    // coding 
  }
}

for/in循环以不同的顺序遍历对象的属性。通常数组元素的遍历实现是升序的,但不能保证一定是这样。如果数组同时拥有对象属性和数组元素,返回的属性名很可能是按照创建的顺序而非数值大小顺序。

    var data = [1, 2, 3, 4, 5];
    var sumOfSquares = 0;
    data.forEach(function (x) {
      sumOfSquares += x * x;
    });
    sumOfSquares;

八、多维数组

    var table = new Array(10);
    var i,
        tableLen = talbe.length,
        row,
        rowLen,
        col;
    for (i = 0; i < table.length; i += 1) {
      table[i] = new Array(10);
    }
    
    for (row = 0; row < tableLen; row += 1) {
      for (col = 0, rowLen = table[row].length; col < rowLen; col += 1) {
        table[row][col] = row * col;
      }
    }
    var product = table[5][7];

九、数组方法

    //Array.join()方法是String.split()方法的逆向操作
    var a = [1, 2, 3];
    a.join();
    a.join(" ");
    a.join("");
    var b = new Array(10);
    b.join('-');
    //Array.reverse()
    var a = [1, 2, 3];
    a.reverse().join()  // "3,2,1"; a: [3, 2, 1]
    //Array.sort()
    var a = new Array("banana", "cherry", "apple");
    a.sort();
    var s = a.join(', '); // "apple banana cherry"

    var a = [33, 4, 1111, 222];
    a.sort();
    a.sort(function (a, b) {
      return a - b;
    });
    a.sort(function (a, b) {
      return b -a; 
    });
    
    a = ['ant', 'Bug', 'cat', 'Dog'];
    a.sort();
    a.sort(function (s, t) {
      var a = s.toLowerCase(),
          b = t.toLowerCase();
      if (a < b) {
        return -1;
      }
      if (a > b) {
        return 1;
      }
      return 0;
    });
    //Array.concat
    var a = [1, 2, 3];
    a.concat(4, 5);
    a.concat([4, 5]);
    a.concat([4, 5], [6, 7]);
    a.concat(4, [5, [6, 7] ]);
    //Array.slice()
    var a = [1, 2, 3, 4, 5];
    a.slice(0, 3);              // 返回[1, 2, 3]
    a.slice(3);                 // 返回[4, 5]
    a.slice(1, -1);             // 返回[2, 3, 4]
    a.slice(-3, -2);            // 返回[3]
    //Array.splice():数组插入或删除元素的通用方法。
    var a = [1, 2, 3, 4, 5, 6, 7, 8];
    a.splice(4);                        // 返回[5, 6, 7, 8];a 是[1, 2, 3, 4]
    a.splice(1, 2);                     // 返回[2, 3]; a 是[1, 4]
    a.splice(1, 1);                     // 返回[4];a 是[1]
    a.splice(0, 1);                     // 返回[1]; a 是[]
    a.splice(0, 1);                     // 返回[]; a 是[]
    // Array.push() Array.pop() 
    var stack = [];             // stack:[]
    stack.push(1, 2);           // stack:[1, 2]       返回 2
    stack.pop();                // stack:[1]          返回 2
    stack.push(3);              // stack: [1, 3]       返回 2
    stack.pop();                // stack:[1]          返回 3
    stack.push([4, 5]);         // stack:[1, [4, 5]]  返回 2
    stack.pop();                // stack:[1]          返回 [4, 5]
    stack.pop();                // stack:[]           返回 1
    // Array.unshift() Array.shift()
    var a = [];                       // a:[]
    a.unshift(1);                     // a:[1]            返回:1
    a.unshift(22);                    // a:[22, 1]        返回:2
    a.shift();                        // a:[1]            返回:22
    a.unshift(3, [4, 5]);             // a:[3, [4, 5], 1] 返回:3
    a.shift();                        // a:[[4, 5], 1]    返回:3
    a.shift();                        // a:[1]            返回:[4, 5]
    a.shift();                        // a:[]             返回:1
    //Array.toString()和Array.toLocaleString()
    [1, 2, 3].toString();                         // '1,2,3'
    ["a", "b", "c"].toString();                   // 'a,b,c'
    [1, [2, 'c'] ].toString();                    // '1,2,c'

十、ECMAScript 5中的数组方法

    // forEach()
    var data = [1, 2, 3, 4, 5];
    var sum = 0;
    data.forEach(function (value) { sum += value; });
    sum;
    data.forEach(function (v, i, a) { a[i] = v + 1; } );
    data;

    function foreach(a, f, t) {
      try { 
        a.forEach(f, t); 
      } catch (e) {
        if () {
          return;
        } else {
          throw e;
        }
      }
    }
    foreach.break = new Error("StopIteration");
    // Array.map()
    var a = [1, 2, 3];
    b = a.map(function (x) { 
            return x * x; 
        });
    // Array.filter()
    var a = [5, 4, 3, 2, 1];
    smallvalues = a.filter(function (x) {
              return x < 3;
            });
    everyother = a.filter(function (x, i) {
              return i % 2 == 0;
            });

    var dense = sparse.filter(functiin () {
              return true;
            });
    a = a.filter(function (x) {
            return x !== undefined && x != null;
            });
    // Array.every()
    var a = [1, 2, 3, 4, 5];
    a.every(function (x) {
              return x < 10;
            });
    a.every(function (x) {
              return x % 2 === 0;
            });
    // Array.some()
    var a = [1, 2, 3, 4, 5];
    a.some(function (x) {
              return x % 2 === 0;
            });
    a.some(isNaN);
    // Array.reduce()
    var a = [1, 2, 3, 4, 5];
    var sum = a.reduce(function (x, y) { 
              return x + y 
            }, 0);
    var product = a.reduce(function (x, y) {
              return x * y;
            }, 1);
    var max = a.reduce(function (x, y) {
              return x > y ? x : y
            });
    //Array.reduceRight()
    var a = [2, 3, 4];
    var big = a.reduceRight(function (accumulator, value) {
              return Math.pow(value, accumulator);
            });
    // Array.reduceRight()
    function union(o, p) {
      return extend(extend({}, o), p);
    }
    var objects = [{x: 1}, {y: 2}, {z: 3}];
    var merged = objects.reduce(union);            // {x: 1, y: 2, z: 3}
    
    var objects = [{x: 1, a: 1}, {y: 2, a: 2}, {z: 3, a: 3}];
    var leftunion = objects.reduce(union);         // {x: 1, y: 2, z: 3, a: 1}
    var rightunion = objects.reduceRight(union);   // {x: 1, y: 2, z: 3, a: 3}
    var a = [0, 1, 2, 1, 0];
    a.indexOf(1);                  // 1
    a.lastIndexf(1);               // 3
    a.indexOf(3);                  // -1 没有值为3的元素
    function findall(a, x) {
      var results = [],
          len = a.length,
          pos = 0;
      while (pos < len) {
        pos = a.indexOf(x, pos);
        if (pos === -1) {
          break;
        }
        results.push(pos);
        pos = pos + 1;
      }
    }

十一、数组类型

    Array.isArray([]);  // true
    Array.isArray({});  // false
    [] instanceof Array     // true
    ({}) instanceof Array   // false

    //当多窗口或窗体存在时 instanceof操作符检测无效

    var isArray = Function.isArray || function (o) {
      return typeof o === "object" && Object.prototype.toString.call(o) === "[object Array]";
    };

十二、类数组对象

数组的特性。

  • 当有新的元素添加到列表中时,自动更新length属性。
  • 设置length为一个较小值将截断数组。
  • 从Array.prototype中继承一些有用的方法。
  • 其类属性为“Array”。

这些特性让Javascript数组和常规对象有明显的区别。但是它们不是定义数组的本质特性。一种常常完全合理的看法把拥有一个数值length属性和对应非负整数属性的对象看作一种类型的数组(类数组)。

    var a = {};
    var i = 0;
    while (i < 10) {
      a[i] = i * i;
      i += 1;
    }
    a.length = i;
    var total = 0,
        j;
    for (j = 0; j < a.length; j += 1) {
      total += a[j];
    }
    function isArrayLike(o) {
      if (o && typeof o === "object" && isFinite(o.length) && o.length >= 0 && o.length === Math.floor(o.length) && o.length < 4294967296 ) {
        return true;
      } else {
        return false;
      }
    }
    var a = {"0": "a", "1": "b", "2": "c", length: 3};
    Array.prototype.join.call(a, "+");
    Array.prototype.slice.call(a, 0);
    Array.prototype.map.call(a, function () {
              return x.toUpperCase();
            });
    Array.join = Array.join || function (a, sep) {
      return Array.prototype.slice.call(a, from, to);
    };
    Array.slice = Array.slice || function (a, from, to) {
      return Array.prototype.slice.call(a, from, to);
    };
    Array.map = Array.map || function (a, f, thisArg) {
      return Array.prototype.map.call(a, f, thisArg);
    };

十三、作为数组的字符串

    var s = "test";
    s.chartAt(0);
    s[1];
    var s = "JavaScript";
    Array.prototype.join.call(s, " ");
    Array.prototype.filter.call(s, function (x) {
              return x.match(/[^aeiou]/);
            }).join("");

字符串是不可变值,故当他们作为数组看待时,它们是只读的。如push(), sort(), reverse(), splice() 等数组方法会修改数组,它们在字符串上是无效的。不仅如此,使用数组方法修改字符串会导致错误:出错的时候没有提示。



blog comments powered by Disqus