Heim >Web-Frontend >js-Tutorial >JavaScript 数组详解_javascript技巧

JavaScript 数组详解_javascript技巧

WBOY
WBOYOriginal
2016-05-16 17:20:271153Durchsuche

在程序语言中数组的重要性不言而喻,JavaScript中数组也是最常使用的对象之一,数组是值的有序集合,由于弱类型的原因,JavaScript中数组十分灵活、强大,不像是Java等强类型高级语言数组只能存放同一类型或其子类型元素,JavaScript在同一个数组中可以存放多种类型的元素,而且是长度也是可以动态调整的,可以随着数据增加或减少自动对数组长度做更改。

创建数组

在JavaScript多种方式创建数组

构造函数

1.无参构造函数,创建一空数组

复制代码 代码如下:
var a1=new Array();

2.一个数字参数构造函数,指定数组长度(由于数组长度可以动态调整,作用并不大),创建指定长度的数组

复制代码 代码如下:
var a2=new Array(5);

3.带有初始化数据的构造函数,创建数组并初始化参数数据

复制代码 代码如下:
var a3=new Array(4,'hello',new Date());

字面量

1.使用方括号,创建空数组,等同于调用无参构造函数

复制代码 代码如下:
var a4=[];

2.使用中括号,并传入初始化数据,等同于调用调用带有初始化数据的构造函数

复制代码 代码如下:
var a5=[10];

注意点

1.在使用构造函数创建数组时如果传入一个数字参数,则会创建一个长度为参数的数组,如果传入多个,则创建一个数组,参数作为初始化数据加到数组中

复制代码 代码如下:

var a1=new Array(5);
            console.log(a1.length);//5
            console.log(a1); //[] ,数组是空的

            var a2=new Array(5,6);
            console.log(a2.length);//2
            console.log(a2); //[5,6]

但是使用字面量方式,无论传入几个参数,都会把参数当作初始化内容

复制代码 代码如下:

var a1=[5];
            console.log(a1.length);//1
            console.log(a1); //[5]

            var a2=[5,6];
            console.log(a2.length);//2
            console.log(a2); //[5,6]

2.使用带初始化参数的方式创建数组的时候,最好最后不要带多余的”,”,在不同的浏览器下对此处理方式不一样

复制代码 代码如下:

var a1=[1,2,3,];
console.log(a1.length);
console.log(a1);

这段脚本在现代浏览器上运行结果和我们设想一样,长度是3,但是在低版本IE下确实长度为4的数组,最后一条数据是undefined

数组的索引与长度

数组的值可以通过自然数索引访问进行读写操作,下标也可以是一个得出非负整数的变量或表达式

复制代码 代码如下:

var a1=[1,2,3,4];
console.log(a1[0]); //1
var i=1;
console.log(a1[i]); //2
console.log(a1[++i]); //3

数组也是对象,我们可以使用索引的奥秘在于,数组会把索引值转换为对应字符串(1=>”1”)作为对象属性名

console.log(1 in a1);//true,确实是一个属性
索引特殊性在于数组会自动更新length属性,当然因为JavaScript语法规定数字不能作为变量名,所以我们不能显示使用array.1这样的格式。由此可见其实负数,甚至非数字”索引“都是允许的,只不过这些会变成数组的属性,而不是索引

复制代码 代码如下:

var a=new Array(1,2,3);
            a[-10]="a[-10]";
            a["sss"]="sss";


image

这样我们可以看出所有的索引都是属性名,但只有自然数(有最大值)才是索引,一般我们在使用数组的时候不会出现数组越界错误也正是因为此,数组的索引可以不是连续的,访问index不存在的元素的时候返回undefined

复制代码 代码如下:

var a=new Array(1,2,3);
            a[100]=100;
            console.log(a.length); //101
            console.log(a[3]); //undefined
            console.log(a[99]); //undefined
            console.log(a[100]); 100

image

上面的例子中,虽然直接对a[100]赋值不会影响a[4]或a[99],但数组的长度却受到影响,数组length属性等于数组中最大的index+1,我们知道数组的length属性同样是个可写的属性,当强制把数组的length属性值设置为小于等于最大index值时,数组会自动删除indexd大于等于length的数据,在刚才代码中追加几句

复制代码 代码如下:

a.length=2
console.log(a);//[1,2]

这时候会发现a[2]和a[100]被自动删除了,同理,如果把length设置为大于最大index+1的值的时候,数组也会自动扩张,但是不会为数组添加新元素,只是在尾部追加空空间

复制代码 代码如下:

a.length=5;
console.log(a); //[1,2] //后面没有3个undefined

元素添加/删除

基本方法

上面例子已经用到向数组内添加元素方法,直接使用索引就可以(index没必要连续)

复制代码 代码如下:

var a=new Array(1,2,3);
a[3]=4;
console.log(a);//[1, 2, 3, 4]

前面提到数组也是对象,索引只是特殊的属性,所以我们可以使用删除对象属性的方法,使用delete 删除数组元素

复制代码 代码如下:

delete a[2];
console.log(a[2]); //undefined

这样和直接把a[2]赋值为undefined类似,不会改变数组长度,也不会改变其他数据的index和value对应关系

image

栈方法

上面例子总有同学就发现了,尤其是其删除方法,并不是我们希望的表现形式,我们很多时候希望删除中间一个元素后,后面元素的index都自动减一,数组length同时减一,就好像在一个堆栈中拿去的一个,数组已经帮我们做好了这种操作方式,pop和push能够让我们使用堆栈那样先入后出使用数组

复制代码 代码如下:

var a=new Array(1,2,3);
            a.push(4);
            console.log(a);//[1, 2, 3, 4]
            console.log(a.length);//4
            console.log(a.pop(a));//4
            console.log(a); //[1, 2, 3]
            console.log(a.length);//3

队列方法

既然栈方法都实现了,先入先出的队列怎么能少,shift方法可以删除数组index最小元素,并使后面元素index都减一,length也减一,这样使用shift/push就可以模拟队列了,当然与shift方法对应的有一个unshift方法,用于向数组头部添加一个元素

复制代码 代码如下:

var a=new Array(1,2,3);
            a.unshift(4);
            console.log(a);//[4, 1, 2, 3]
            console.log(a.length);//4
            console.log(a.shift(a));//4
            console.log(a); //[1, 2, 3]
            console.log(a.length);//3

终极神器

JavaScript提供了一个splice方法用于一次性解决数组添加、删除(这两种方法一结合就可以达到替换效果),方法有三个参数

1.开始索引

2.删除元素的位移

3.插入的新元素,当然也可以写多个

splice方法返回一个由删除元素组成的新数组,没有删除则返回空数组

复制代码 代码如下:
var a=new Array(1,2,3,4,5);

删除

指定前两个参数,可以使用splice删除数组元素,同样会带来索引调整及length调整

复制代码 代码如下:

var a=new Array(1,2,3,4,5);
            console.log(a.splice(1,3));//[2, 3, 4]
            console.log(a.length);//2
            console.log(a);//[1,5]

如果数组索引不是从0开始的,那么结果会很有意思,有一这样数组

复制代码 代码如下:

var a=new Array();
        a[2]=2;
        a[3]=3;
        a[7]=4;
        a[8]=5;

image

复制代码 代码如下:

console.log(a.splice(3,4)); //[3]
        console.log(a.length); //5
        console.log(a); //[2: 2, 3: 4, 4: 5]


image

上面例子可以看到,splice的第一个参数是绝对索引值,而不是相对于数组索引,第二个参数并不是删除元素的个数,而是删除动作执行多少次,并不是按数组实际索引移动,而是连续移动。同时调整后面元素索引,前面索引不理会

插入与替换

只要方法第二个参数,也就是删除动作执行的次数设为0,第三个参数及以后填写要插入内容就splice就能执行插入操作,而如果第二个参数不为0则变成了先在该位置删除再插入,也就是替换效果

复制代码 代码如下:

var a=new Array(1,2,3,4,5);
       a.splice(1,0,9,99,999);
       console.log(a.length); //8
       console.log(a);//[1, 9, 99, 999, 2, 3, 4, 5]
       a.splice(1,3,8,88,888);
       console.log(a.length);//8
       console.log(a);//[1, 8, 88, 888, 2, 3, 4, 5]


常用方法

join(char)

这个方法在C#等语言中也有,作用是把数组元素(对象调用其toString()方法)使用参数作为连接符连接成一字符串

复制代码 代码如下:

var a=new Array(1,2,3,4,5);
       console.log(a.join(',')); //1,2,3,4,5
       console.log(a.join(' ')); //1 2 3 4 5
slice(start,end)

不要和splice方法混淆,slice

复制代码 代码如下:

var a=new Array(1,2,3,4,5);
            console.log(a); //[1, 2, 3, 4, 5]
            console.log(a.slice(1,2));//
            console.log(a.slice(1,-1));//[2, 3, 4]
            console.log(a.slice(3,2));//[]
            console.log(a); //[1, 2, 3, 4, 5]

方法用于返回数组中一个片段或子数组,如果只写一个参数返回参数到数组结束部分,如果参数出现负数,则从数组尾部计数(-3意思是数组倒第三个,一般人不会这么干,但是在不知道数组长度,想舍弃后n个的时候有些用,不过数组长度很好知道。。。。,好纠结的用法),如果start大于end返回空数组,值得注意的一点是slice不会改变原数组,而是返回一个新的数组。

concat(array)

看起来像是剪切,但这个真不是形声字,concat方法用于拼接数组,a.concat(b)返回一个a和b共同组成的新数组,同样不会修改任何一个原始数组,也不会递归连接数组内部数组

复制代码 代码如下:

var a=new Array(1,2,3,4,5);
            var b=new Array(6,7,8,9);
            console.log(a.concat(b));//[1, 2, 3, 4, 5, 6, 7, 8, 9]
            console.log(a); //[1, 2, 3, 4, 5]
            console.log(b); //[6, 7, 8, 9]
reverse()

方法用于将数组逆序,与之前不同的是它会修改原数组

复制代码 代码如下:

var a=new Array(1,2,3,4,5);
            a.reverse();
            console.log(a); //[5, 4, 3, 2, 1]

同样,当数组索引不是连续或以0开始,结果需要注意

复制代码 代码如下:

var a=new Array();
        a[2]=2;
        a[3]=3;
        a[7]=4;
        a[8]=5;

image

复制代码 代码如下:

a.reverse();


image

sort

sort方法用于对数组进行排序,当没有参数的时候会按字母表升序排序,如果含有undefined会被排到最后面,对象元素则会调用其toString方法,如果想按照自己定义方式排序,可以传一个排序方法进去,很典型的策略模式,同样sort会改变原数组。

复制代码 代码如下:

var a=new Array(5,4,3,2,1);
       a.sort();
       console.log(a);//[1, 2, 3, 4, 5]

但是。。。

复制代码 代码如下:

var a=new Array(7,8,9,10,11);
       a.sort();
       console.log(a);//[10, 11, 7, 8, 9]

因为按照字母表排序,7就比10大了,这时候我们需要传入自定义排序函数

复制代码 代码如下:

var a=new Array(7,8,9,10,11);
           a.sort(function(v1,v2){
            return v1-v2;
           });
       console.log(a);//[7, 8, 9, 10, 11]

原理和C#中的sort类似(.NET Framework 中的设计模式——应用策略模式为List排序),只不过可以直接传递方法进去,以下内容纯属猜测

sort内部使用快速排序,每次比较两个元素大小的时候如果没有参数,则直接判断字母表,如果有参数,则把正在比较的两个参数传入自定义方法并调用(正在比较的两个数会传给自定义方法的v1、v2),如果返回值大于0表示v1>v2,如果等于0,表示v1=v2,如果小于0,表示v1

最后
了解了这些看看数组真的很了不得啊,即强大有灵活,但是在遍历元素,及获取元素位置等也有一定的不便,这些在ECMAScript中已经得到解决,熟练使用可以让我们的JavaScript优雅而高效。

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn