Js整理备忘(04)——数组基础

概念:数组(array)是一个有序的、值的集合。每个值叫做一个元素(element),每个元素在数组中都有个数字化的位置,叫做下标(index)。

类型:数组是复合数据类型。数组实质上是一种特殊的对象,它是一个具有额外功能层的对象。例如,下面两行代码返回类型都为object

typeof ([1,2]);

var a=[]; typeof(a);

特点:元素数量可以无限多,元素可以是任意类型的数据(同一数组中元素类型可以不同),被赋值的元素下标可以不连续(未定义的元素默认值为undefined)。

 

1、数组的创建

(1)使用数组直接量

var a=[];//定义一个没有元素的数组,即空数组,数组长度为0,此时a[0]==undefined==null

var b=[20,,,["asd",5],"qwe"];//未定义的元素默认为undefined,此时b[1]==undefined

 

(2)使用Array()构造函数

  • 无参数

var a=new Array();//创建一个没有元素的空数组

  • 传n个参数,即指定了数组前n个值,注意不要出现两个连续的逗号"," ,这一点跟数组直接量方式有区别。

var b=new Array(20,["asd",5],"qwe");//跟数组直接量相比,这种方法似乎显得不太方便

  • 传一个数字参数

var a=new Array(10); //创建了一个拥有10个元素的数组,即a.length==10,此时每个元素的值都是undefined

 

2、数组元素的一些操作

只记录一些注意点,需要时可查找相关资料。

数组中无序的属性,不参与数组元素的操作。

(1)添加新元素

  • 通过下标添加元素

通过数组下标,可以随时给数组的任意位置添加任意类型的元素,只需要一个简单的赋值操作即可。例如:

var arr=[];arr[10]="nihao"; //给数组中下标为10的元素(有序序列中的第11个元素)赋值,不需要关心其他位置的元素是否定义。

可见Js中数组可以是稀疏的(sparse),数组中有效值的下标不必须连续。其中没有定义的元素默认值为undefined,Js不会给它分配内存。

  • 通过属性名添加元素

这是数组中比较特别,也比较有趣的一点,主要是由于数组本质上是对象,所以很自然应该具备对象的所有特性。例如:

var a=[];a["name"]="An array for test."; //给数组对象a添加了一个名为“name”的属性,属性值是一个字符串,完全符合语法。

数组与对象的区别与联系(按照自己的理解整理,不一定准确)

<1>数组属于对象的一种,但又高于对象。前面提过,对象中的属性名是标识符或者字符串,而数组的下标理论上应该也可以被看作数组的属性名,只不过这种属性名是用“整数值(即下标值)”表示的。这样看的话数组属于对象似乎就更好理解了。

<2>从定义上来看,对象的属性是无序的,而数组则是有序的值的集合。但数组也是一种对象,所以自然也可以包含无序的属性,这是不是跟定义有点矛盾了呢?但是谁叫Js本来就是一种宽松的语言呢,所以也就犯不着顶真了。有时觉得Js语言很聪明,很会给自己留退路,也很贴近生活。【凡事无绝对,只有矛盾才是绝对存在的。】

不过有一点倒不用担心,这种无序元素的存在不会影响数组的一些正常操作。例如上一个例子中,虽然给空数组a添加了一个“name”属性,但是a.length的值仍然是0。

注:对象并没有length属性。当然length属性也不是数组特有,后面介绍的函数也有length属性,不过意义是不同的。

<3>似乎也可以这样理解,添加了无序属性的数组,变成了这样一个对象,该对象中包含最初定义的传统意义上的数组对象,和额外添加的无序属性。而对该对象的操作,在使用下标时,仍然是直接操作原先定义的那个数组。

 

(2)删除数组元素

  • delete运算符只是将一个数组元素设置成undefined值,但是元素本身仍然存在,即所有元素下标位置不变。
  • 要真正删除一个元素,需使用指定的数组方法:

Array.shift()方法——无参,对数组本身而言总是删除掉第一个元素,返回值即为删除的元素,删除后数组下标自动迁移。

Array.pop()方法——无参,总是删除掉最后一个元素,返回值即为删除的元素,删除后数组下标自动迁移。

Array.splice()方法——传递两个整数参数时,表示从一个数组中删除连续下标范围的元素。

下面数组的方法中还会具体介绍。

 

(3)截断或增长数组

数组的length属性既可以读也可以写。

若设置的新length的值比当前数组的length值小,则数组被“截断”,该长度之外的元素都被抛弃,值也丢失。

若设置的新length的值比当前数组的length值大,则数组被“增长”,新增位置上的值默认为undefined。

这里列举一些例子,说明数组元素的部分操作:

<script type="text/javascript" language="javascript">
    var b = [{ x: 1 }, 20, "abc", , ["asd", 5], true];  //b.length值为6
    delete b[1];        //将元素b[1]的值设为undefined。b应该变为[{x:1},,"abc",,["asd", 5],true]
    b[2] = undefined;   //与上句作用一样。             b应该变为[{x:1},,,,["asd", 5],true]
    b.id = "id";        //给数组对象添加一个名为"id"的无序属性。
    document.write(b.toString() + "<br/>");     //<1> 会输出id吗?
    
    b["id"] = "new value"; //<2> 可以对该添加的无序属性进行操作吗?
    b.pop();            //<3> 删除数组最后一个元素,数组length会变化吗?删除的是有序数组中的“true”,还是新增的元素id呢?
    for (p in b) {
        document.write(p + ":" + b[p]+" ; ");   //<4> 遍历数组元素,会输出id吗?
    }
    document.write("<br/>" + b.length);         //<5> 结果5还是6 ?
</script>

运行后,页面输出的结果如下:
[object Object],,,,asd,5,true
0:[object Object] ; 2:undefined ; 4:asd,5 ; id:new id ;
5

回答运行之前的疑问:

综合问题<1>、<3>和<5>:第一行并没有输出id及其值。而pop()操作,并没有删除id,而是删除了有序数组中最后一个元素“true”。length的值减少了1应该是由pop()导致。

——由结果猜想:对b使用数组内部方法进行操作时,实际上只对其中的原始数组对象操作(即:添加的无序命名属性除外)。并且length的值不受无序属性的影响。只决定于原始的数组。

问题<2>:看结果的第二行,id的值为“new id”,说明数组是可以对添加的无序属性进行操作的

问题<4>:说明用遍历数组的方式(for/in)可以输出当前数组对象中所有的属性值,包括无序属性。

 

3、数组的一些方法

(1)join()方法

——原来的数组不变,返回“数组的所有元素组成的字符串,各元素之间默认用逗号分隔”,返回值类型为字符串(string)。

若指定参数,则结果字符串中各数组元素之间用指定的参数(string类型)隔开,若不指定参数,则使用逗号分隔。例:

<script language="javascript" type="text/javascript">
    var a = [1, 2, "asd", 4];
    document.write(a.join());       // 1,2,asd,4
    document.write(a.join("0"));    // 1020304
    document.write(a.join("*"));    // 1*2*asd*4
    document.write(a.toString());   // 1,2,asd,4 原数组不变
</script>
该方法恰好与String.split()相反,后者通过将一个字符串分割成几个片段来创建一个数组。
 

(2)reverse()方法

——直接对原数组操作,返回将数组元素倒序排列后的数组。结果如下:

var a = [1, 2, "asd", 4];
document.write(a.reverse());    //4,asd,2,1
document.write(a.toString());   //4,asd,2,1

 

(3)sort()方法

——直接对原数组操作,返回排序后的数组。注意以下几点:

  • 若不指定参数,它将按照字母顺序对数组元素排序(即使数组元素全是数字 )
var a = [33, 4, 111, 22, 234, 12];
document.write(a.sort()); //结果:111,12,22,234,33,4
  • 若数组中含有未定义的元素,这些元素将被放在数组的末尾。
  • 若要将数组按照别的顺序排序,必须使用一个比较函数作为sort()方法的参数,

例如以下将数组将按照数值大小排序:

document.write(a.sort(
    function(a, b) {
        return a - b;//按数字升序排序: 4,12,22,33,111,234
    }
) );
document.write(a.sort(
    function(a, b) {
        return b - a;//按数字降序排序: 234,111,33,22,12,4
    }
));

上面的例子是将函数直接量作为sort()方法的参数的,也可以传递函数名。如下,将忽略字母大小写进行升序排列:

function f(s1, s2) { 
    if (s1.toLowerCase() < s2.toLowerCase()) {
        return -1;
    }
    else if (s1.toLowerCase() > s2.toLowerCase()) {
        return 1;
    }
    else return 0;
}//先定义一个比较函数f
var str = ["agp", "AadDf", "Better"];
document.write(str.sort(f));//结果显示:AadDf,agp,Better

 

(4)slice()方法

——原来的数组不变,返回指定数组的一个片段(slice),或者说是子数组。注意几点:

若只传递一个参数,则返回的数组为以参数数值为起点下标到原数组结束处的所有元素。

若传递两个参数,则参数分别表示返回片段的起止下标位置。

可以传递负整数,参数值-1是指数组的倒数第一个元素。(较容易理解,示例省略)

 

(5)splice()方法

——这是插入或删除数组元素的通用方法。

——直接对原数组操作,原数组变成处理后的数组,返回删除掉的元素组成的数组。

该方法可以设置多个参数:第一个参数指定位置,第二个参数指定删除的元素个数。后面还可以有任意多个参数,表示在该位置要新插入的数组元素。

一些例子说明:

var p, q;
p = [1, 2, 3, 4, 5];
q = p.splice(3);    //p=[1,2,3]; q=[4,5]
q = p.splice(1, 2); //p=[1]; q=[2,3]
var m, n;
m = [1, 2, 3, 4, 5];
n = m.splice(2, 0, 'a', 'b'); //m=[1,2,'a','b',3,4,5]; n:[]
n = m.splice(2, 2, [1, 2], 3); //m=[1,2,[1,2],3,3,4,5]; n:['a','b']

(6)push()、pop()、shift()、unshift()

push()——将一个或多个新元素附加到指定数组后面。

pop() ——直接对数组操作,删除最后一个数组元素,返回删除的值,注意,pop无参,每次只删除一个值。

shift()——直接对数组操作,删除并返回第一个数组元素。

unshift()——将一个或多个新元素附加到指定数组开头。

 

(7)一些新增方法

自 FireFox 1.5 起,开始支持 JavaScript 1.6 , 在 JavaScript 1.6 里,javascript 数组增加了几个非常有用的方法:indexOf、lastIndexOf、every、 filter、 forEach、 map、 some,其中前两个可以用于元素快速定位,而后面的几个则可以归为迭代(iterative)方法。

但是,这些新方法并非所有浏览器都支持,有兴趣的话,可以参考:Javascript 1.6 数组新增方法介绍 ,逐个介绍这些方法的使用,以及针对不支持的浏览器的处理办法。

 

4、类似数组的对象

本文上面整理的“数组与对象的区别与联系”中也提到一点:数组中有length属性而对象中没有。

猜想:那是不是说如果一开始定义的是一个对象,然后给它添加上length属性,它就可以作为数组一样处理呢?(当然它应该不可以完全变成数组,只是可以将它当作“类似数组的对象”)

这种类似数组的对象虽然具有length属性,但是并不能调用数组的方法,因为其本质并不是数组。

不过,可以使用遍历数组的代码来遍历这种对象。例如:

<script language="javascript" type="text/javascript">
    var a = {};     //定义对象
    for (var i = 0; i < 10; i++) {
        a[i] = i * i;
    }
    a.length = i;   //这里很关键,因为对象本身没有length属性
    
    for (var j = 0; j < a.length; j++) {
        document.write(a[j] + ";");//结果输出:0;1;4;9;16;25;36;49;64;81;
    }    
</script>

分析:在给a对象添加属性时,a[i]中的 i 理论上应该会被转换为字符串处理,下图证明了这一猜想:

1

但是若对一个数组,可不可以使用数字字符串作为下标访问其元素呢???

——答案是:可以的。

posted on 2010-01-13 09:59  lihua好心情  阅读(501)  评论(0编辑  收藏  举报