JavaScript-Array-数组-方法-属性-循环

一、方法介绍

1. shift:删除原数组第一项,并返回删除元素的值;如果数组为空则返回undefined 

var a = [1,2,3,4,5]; 
var b = a.shift(); //a:[2,3,4,5] b:1

2. unshift:将参数添加到原数组开头,并返回数组的长度 

var a = [1,2,3,4,5]; 
var b = a.unshift(-2,-1); //a:[-2,-1,1,2,3,4,5] b:7 

注:在IE6.0下测试返回值总为undefined,FF2.0下测试返回值为7,所以这个方法的返回值不可靠,需要用返回值时可用splice代替本方法来使用。

3. pop:删除原数组最后一项,并返回删除元素的值;如果数组为空则返回undefined 

var a = [1,2,3,4,5]; 
var b = a.pop(); //a:[1,2,3,4] b:5

4. push:将参数添加到原数组末尾,并返回数组的长度 

var a = [1,2,3,4,5]; 
var b = a.push(6,7); //a:[1,2,3,4,5,6,7] b:7

5. concat:返回一个新数组,是将参数添加到原数组中构成的 

var a = [1,2,3,4,5]; 
var b = a.concat(6,7); //a:[1,2,3,4,5] b:[1,2,3,4,5,6,7]

6. splice(start,deleteCount,val1,val2,...):从start位置开始删除deleteCount项,并从该位置起插入val1,val2,... 

var a = [1,2,3,4,5]; 
var b = a.splice(2,2,7,8,9); //a:[1,2,7,8,9,5] b:[3,4] 
var b = a.splice(0,1); //同shift 
a.splice(0,0,-2,-1); var b = a.length; //同unshift 
var b = a.splice(a.length-1,1); //同pop 
a.splice(a.length,0,6,7); var b = a.length; //同push

7. reverse:将数组反序 

var a = [1,2,3,4,5]; 
var b = a.reverse(); //a:[5,4,3,2,1] b:[5,4,3,2,1]

8. sort(orderfunction):按指定的参数对数组进行排序 

var a = [1,2,3,4,5]; 
var b = a.sort(); //a:[1,2,3,4,5] b:[1,2,3,4,5]

9. slice(start,end):返回从原数组中指定开始下标到结束下标之间的项组成的新数组 

var a = [1,2,3,4,5]; 
var b = a.slice(2,5); //a:[1,2,3,4,5] b:[3,4,5]

10. join(separator):将数组的元素组起一个字符串,以separator为分隔符,省略的话则用默认用逗号为分隔符 

 

var a = [1,2,3,4,5]; 
var b = a.join("|"); //a:[1,2,3,4,5] b:"1|2|3|4|5"

例子:
<script type="text/javascript">
//JS Array.join 将数组元素连接成字符串
//在JavaScript中,数组对象 Array的方法arr.join([separator])将所有元素连接成一个字符串。参数separator是一个可选的字符串,用作分隔符。
//例1:
var cnb = ["零","一","二","三","四","五","六","七","八","九","十"];
document.writeln(cnb.join()); // 输出:零,一,二,三,四,五,六,七,八,九,十
document.writeln(cnb.join("|")); // 输出:零|一|二|三|四|五|六|七|八|九|十
//例2:
var cnb = [1,2,3];
cnb[10] = "10";
document.writeln(cnb.join()); // 输出:1,2,3,,,,,,,,10
document.writeln(cnb.join("|")); // 输出:1|2|3||||||||10
//例3:
var num = [],sum = 0;
for(var i=1; i<=10; i++){
 num.push(i);
 sum += i;
}
document.writeln(num.join("+") + "=" + sum); // 输出:1+2+3+4+5+6+7+8+9+10=55
//==================================================================================================
//String.split(delimiter,max_array_length)方法 与 Array.join([separator])方法执行相反的操作:
var num = "1,2,3,4,5,6,7,8,9,10".split(",");
document.writeln(num.join("-")); // 输出:1-2-3-4-5-6-7-8-9-10
</script>

 

数组是JavaScript提供的一个内部对象,它是一个标准的集合,我们可以添加(push)、删除(shift)里面元素,我们还可以通过for循环遍历里面的元素,那么除了数组我们在JavaScript里还可以有别的集合吗?

 

  由于JavaScript的语言特性,我们可以向通用对象动态添加和删除属性。所以Object也可以看成是JS的一种特殊的集合。下面比较一下Array和Object的特性:

 

Array:

 

新建:var ary = new Array(); 或 var ary = []; 
增加:ary.push(value); 
删除:delete ary[n]; 
遍历:for ( var i=0 ; i < ary.length ; ++i ) ary[i];

 

Object:

 

新建:var obj = new Object(); 或 var obj = {}; 
增加:obj[key] = value; (key为string) 
删除:delete obj[key]; 
遍历:for ( var key in obj ) obj[key];

 

从上面的比较可以看出Object完全可以作为一个集合来使用,在使用Popup窗口创建无限级Web页菜单(3)中我介绍过Eric实现的那个__MenuCache__,它也就是一个模拟的集合对象。

 

  如果我们要在Array中检索出一个指定的值,我们需要遍历整个数组:

代码: 

var keyword = ; 
  for ( var i=0 ; i < ary.length ; ++i )  { 
    if ( ary[i] == keyword ) { 

    // todo 

    } 
  }


  而我们在Object中检索一个指定的key的条目,只需要是要使用: 

代码: 

var key = ''; 
  var value = obj[key]; 
  // todo

 Object的这个特性可以用来高效的检索Unique的字符串集合,遍历Array的时间复杂度是O(n),而遍历Object的时间复杂度是O(1)。虽然对于10000次集合的for检索代价也就几十ms,可是如果是1000*1000次检索或更多,使用Object的优势一下就体现出来了。在此之前我做了一个mapping,把100个Unique的字符mapping到1000个字符串数组上,耗时25-30s!后来把for遍历改成了Object模拟的集合的成员引用,同样的数据量mapping,耗时仅1.7-2s!!!

  对于集合的遍历效率(从高到低):var value = obj[key]; > for ( ; ; ) > for ( in )。效率最差的就是for( in )了,如果集合过大,尽量不要使用for ( in )遍历。

数组是元素的一个有序组合。在JavaScript中,数组可以使用正式的对象表示法来创建,或者可以使用直接量表示法来初始化。

var arrObject = new Array("val1", "val2"); // 作为对象的数组
var arrLiteral = ["val1", "val2"]; // 数组直接量

对于开发者来说,这没有区别:在直接量和对象上都可以调用一个Array方法。对于JavaScript引擎来说,每次访问数组直接量的时候,必须重新解释它,特别是在一个函数中使用它的时候。

  使用new运算符来创建一个新的Array对象:

var arrObject = new Array();

也可以创建带有某些值的一个新数组:

var arrObject = new Array("val1", "val2");

JavaScript中的数组是从0开始索引的,这意味着,第一个元素的索引是0,最后一个元素是数组的长度减去1。

1、循环遍历数组

 问题:想要很容易地访问数组的所有元素。

  解决方案:

  要访问一个数组,最常用的方法是使用for循环:

<script type="text/javascript">
    var animals = new Array("cat", "dog", "whale", "seal");
    var animalString = "";
    for (var i = 0; i < animals.length - 1; i++) {
        animalString += animals[i] + " ";
    }
    alert(animalString);
</script>

讨论:

  for循环可以用来访问数组的每一个元素。数组从0开始,而且数组属性length用来设定循环结束。

2、按顺序存储和访问值

问题:想要以这样一种方式来存储值,可以按照存储它们的方式来顺序访问值;

  解决方案:

  要按照接受值的顺序来存储和访问值,创建一个先进先出(FIFO)的队列。使用JavaScript Array对象的push方法,向队列添加项,并且用shift来获取项:

<script type="text/javascript">
    // 创建新的数组
    var queue = new Array();

    // 压入3个条目
    queue.push("first");
    queue.push("second");
    queue.push("third");

    // 获取两个条目
    alert(queue.shift());
    alert(queue.shift());
    alert(queue);
</script>

讨论:

  Array push方法创建一个新的数组元素,并且将其添加到数组的末尾:

queue.push("first");

每次压入一个元素,数组元素的计数自增。

  Array shift方法从数组前面提取数组元素,将其从数组中删除,并且返回该元素:

var elem = queue.shift();

对于每一个shift操作的元素,数组元素会自减,因为shift除了返回该项,还会修改数组。

3、以相反的顺序存储和访问值

问题:想要以一种方式来存储值,即以相反的顺序访问值,先访问最近存储的值,也就是一个后进先出(LIFO)的栈。

  解决方案:

  要以相反的顺序存储值,创建一个LIFO栈。使用JavaScript Array对象的push方法来想栈添加项,使用pop方法来获取项:

<script type="text/javascript">
    // 创建新的数组
    var stack = new Array();

    // 压入3个条目
    stack.push("first");
    stack.push("second");
    stack.push("third");

    // 弹出两个条目
    alert(stack.pop()); // 返回第三个条目
    alert(stack.pop()); // 返回第二个条目
    alert(stack); // 返回第一个条目
</script>

讨论:

  栈也是一个数组,其中每个新添加的元素位于栈的顶部,并且按照后进先出的顺序获取。

  Array push方法创建一个新的元素,并将其添加到数组的尾部:

stack.push("first");

 每次压入元素的时候,数组元素的计数都会自增。

  Array pop方法从数组的尾部提取数组元素,将其从数组中移走,并返回元素:

var elem = stack.pop();

每次弹出一个元素的时候,数组元素计数会自减,因为弹出也修改了数组。

4、在数组中搜索

  问题:想要在数组中搜索一个特定值,如果找到的话,获取该数组元素的索引。

  解决方案:

  使用新的(ECMAScript 5)Array对象方法indeOf和lastIndexOf:

<script type="text/javascript">
    var animals = new Array("dog", "cat", "seal", "elephant", "lion");
    alert(animals.indexOf("elephant")); // 打印出 3
    alert(animals.indexOf("seal", 2)); // 打印出 2
</script>

尽管浏览器中有时候对indexOf和lastIndexOf都是支持的,但是,这只是ECMAScript 5的版本中正式化了。这两个方法都接受一个搜索值,然后,将其与数组中的每个元素比较。如果找到了该值,两个方法都返回该数组元素的一个索引。如果没有找到值,返回-1.indexOf返回找到的第一个元素,lastIndexOf返回找到的最后一个元素。

  参见:

  并非所有的浏览器都支持indexOf和lastindexOf,针对这一函数的解决方案:

<script type="text/javascript">
    if (!Array.prototype.indexOf) {
        Array.prototype.indexOf = function (elt/*, from*/) {
            var len = this.length >>> 0;
            var from = Number(arguments[1]) || 0;
            from = (from < 0) ? Math.ceil(from) : Math.floor(from);

            if (from < 0) {
                from += len;
            }

            for (; from < len; from++) {
                if (from in this && this[from] === elt) {
                    return from;
                }
            }

            return -1;
        }
    }
</script>

5、对每个数字元素应用一个函数

 问题:想要使用一个函数来检查一个数组值,如果满足给定的条件,就替换它。

  解决方案:

  使用新的ECMAScript 5 Array对象的forEach方法,来针对每个数组元素都绑定一个回调函数:

<script type="text/javascript">
    function replaceElement(element, index, array) {
        if (element == "ab") {
            array[index] = "**";
        }
    }

    var charSets = new Array("ab", "bb", "cd", "ab", "cc", "ab", "dd", "ab");
    //对每个数组元素应用函数
    charSets.forEach(replaceElement)
    alert(charSets); // 打印出**,bb,cd,**,cc,**,dd,**
</script>

 讨论:

  forEach方法接受一个参数,这个参数是个函数。该函数自身有3个参数:数组元素,元素的索引和数组。

  参见:

  大多数浏览器都支持forEach。然而,对于那些不支持的浏览器,可以使用Array.prototype属性来模拟forEach行为。

<script type="text/javascript">
    if (!Array.prototype.forEach) {
        Array.prototype.forEach = function (fun/*, thisp*/) {
            var len = this.length >>> 0;
            if (typeof fun != "function") {
                throw new TypeError();
            }

            var thisp = arguments[1];
            for (var i = 0; i < len; i++) {
                if (i in this) {
                    fun.call(thisp, this[i], i, this);
                }
            }
        };
    }
</script>

6、创建一个过滤后的数组

问题:想要过滤一个数组中的元素的值,并且把结果赋给一个新的数组。

  解决方案:

  使用Array对象的filter方法:

<script type="text/javascript">
    function removeChars(element, index, array) {
        return element !== "**";
    }
    var charSets = new Array("**", "bb", "cd", "**", "cc", "**", "dd", "**");
    var newArray = charSets.filter(removeChars);
    alert(newArray); // bb,cd,cc,dd
</script>

讨论:

  filter方法是ECMAScript 5新添加的方法,该方法将一个回调函数应用于每一个数组元素。作为参数传递给filter方法的函数返回一个布尔值,true或false,根据测试数组元素的结果来返回。这个返回值决定了该数组元素是否添加到一个新的数组中,如果函数返回true,将会添加;否则,将不会添加。

  参见:

  对于不支持filter方法的浏览器的模拟实现:

<script type="text/javascript">
    if (!Array.prototype.filter) {
        Array.prototype.filter = function (fun/*, thisp*/) {
            var len = this.length >>> 0;
            if (typeof fun != "function") {
                throw new TypeError();
            }

            var res = new Array();
            var thisp = arguments[1];
            for (var i = 0; i < len; i++) {
                if (i in this) {
                    var val = this[i]; // 放置fun修改了this
                    if (fun.call(thisp, val, i, this)) {
                        res.push(val);
                    }
                }
            }

            return res;
        };
    }
</script>

7、验证数组内容

问题:想要确保一个数组满足某个条件。

  解决方案:

  使用Array对象的every方法来检查给定条件的每个元素。

<script type="text/javascript">
    function testValue(element, index, array) {
        var re = /^[a-zA-Z]+$/;
        return re.test(element);
    }
    var elemSet = new Array("**", 123, "abc", "-", "AAA");
    alert(elemSet.every(testValue));
</script>

讨论:

  Array对象的every和some方法都是最新的ECMAScript 5 Array方法,不同之处在于当使用every方法的时候,只要该函数返回一个false值,处理就会结束,并且该方法返回false。而some方法将继续测试每一个数组元素,知道回调函数返回true。此时不再验证其他的元素,该方法返回true。如果回调函数测试了所有的元素,并且任何时候不会返回true,some方法返回false。

  参见:

  对于不支持every和some的浏览器的实现方式:

<script type="text/javascript">
    if (!Array.prototype.some) {
        Array.prototype.some = function (fun/*, thisp*/) {
            var i = 0,
                len = this.length >>> 0;
            if (typeof fun != "function") {
                throw new TypeError();
            }

            var thisp = arguments[1];
            for (; i < len; i++) {
                if (i in this
                    && fun.call(thisp, val, i, this)) {
                    return true
                }
            }

            return false;
        };
    }

    if (!Array.prototype.every) {
        Array.prototype.every = function (fun/*, thisp*/) {
            var len = this.length >>> 0;
            if (typeof fun != "function") {
                throw new TypeError();
            }

            var thisp = arguments[1];
            for (var i=0; i < len; i++) {
                if (i in this
                    && fun.call(thisp, val, i, this)) {
                    return false
                }
            }

            return true;
        };
    }
</script>

 

posted @ 2014-12-22 19:25  贝壳风铃  阅读(192)  评论(0)    收藏  举报