zoukankan      html  css  js  c++  java
  • 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

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

    ——答案是:可以的。

  • 相关阅读:
    数据变换
    离群点的检验
    数据清洗
    数据采样
    FM与FFM
    EM算法与高斯混合模型
    最大熵模型
    PageRank
    软件技术基础
    原来炫酷的可视化地图,用Python就能搞定!
  • 原文地址:https://www.cnblogs.com/gppblog/p/1646226.html
Copyright © 2011-2022 走看看