JavaScript中的数组详解

时间:2022-07-25 14:08:26

JavaScript中的数组

一、数组的定义

  数组是值的有序集合,或者说数组都是数据的有序列表。

二、创建数组

字面量形式

1、空数组

  var arr=[];

2、带有元素的数组

  var arr=[1,2,3,1,2];

3、数组值可以是任意类型

  var arr=[1,2.3,'foodoir',true,null,undefined,[1,2,3],{name:'foodoir',age:21}];

  注意:

    1、数组字面量中的值不一定是常量,它们可以是任意表达式;

    2、它可以包含对象字面量({name:'foodoir',age:21})和其它数组字面量([1,2,3]);

    3、如果数组的元素还是数组,就形成了多维数组,如:var arr=[[1,2,3],[4,[5,6]]];

    4、使用数字字面量表示法时,不会调用Array构造函数。

4、省略数组中的某个值,默认值为undefined

  var arr=[1,,3]//相当于[1,undefined,3]

  省略数组中的某个值,从而导致该数组变为了稀疏数组,此时需要注意的是

    1、var arr=[,,],这种方法在不同的浏览器下面,运行的结果不一样

      在ie8中,会在末尾添加undefined的值,比如说var arr=[1,2,],相当于[1,2,undefined],此时数组的长度为3

      在其它浏览器中会自动忽略最后的逗号,比如说var arr=[1,2,],相当于[1,2],此时数组的长度为2

    2、除了通过字面量的方式直接构造稀疏数组之外,还可以通过delete操作符来构造,具体见后面关于delete的介绍

    !import:足够稀疏的数组通常在实现上比稠密数组(连续数组)更慢,内存利用率更高,在这样的数组中查找元素的时间与常规对象属性的查找时间一样长!

通过构造函数Array()创建数组

1、调用时没有参数

  var arr=new Array()

  注意

    空数组,等同于arr=[];

2、调用时传递一个参数

  var arr=new Array(5);

  注意

    1、代表指定了数组的长度为5,等同于var arr=[];arr.length=5;

    2、如果是:var arr=new Array[5];  //输出:undefined is not a function  此时应该注意到Array后面的符号,不然容易出错  

    3、如果是:var arr=new Array('5');console.log(a[0],a.length);  //5,1  说明此时创建的数组只有一项,它的长度为1,值为5

  如果预先知道数组元素个数,可以通过参数指定,这种形式的Array()构造函数可以用来分配一个数组空间。

3、超过两个参数

  var arr=new Array(1,2.3,'foodoir',null,undefined,true,false,[1,23,4]);

  注意

  显示指定了数组中的值,可以为多种类型,与var arr=[1,2.3,'foodoir',true,null,undefined,[1,2,3],{name:'foodoir',age:21}];类似;

另外:在使用Array()构造函数时,可以省略new操作符,比如:var arr=Array(1,2,3);

三、使用数组

1、根据下标找到对应的值

    arr[下标]=值;

//通过下标读取值
  var arr = [1,2,3,4];
  console.log(arr[0]);//1,说明数组的下标从0开始
  console.log(arr[4]);//undefined,数组的长度为4,取不到arr[4]的值
//修改之前的值
  arr[0] = 'hello';
  console.log(arr);//hello,2,3

  注意:数组中的下标是从0开始

2、向数组中添加元素

  arr[下标]=值;

  arr.push(值,...):数组末尾添加元素

  arr.unshift(值,...):数组开始添加元素

		//通过下标向数组中添加一个值
var arr = [1,2,3,4];
arr[4] = 'world';
console.log(arr);//1,2,3,4,world
arr[9] = 10;
console.log(arr);//1,2,3,4,world,,,,,10
//也可以这样
var x= 2;
console.log(arr[x]);//3
arr[x] = 333;
console.log(arr);//1,2,333,4,world,,,,,10 //在数组的末尾添加一个或多个元素push()
var arr = [];
arr[0] = 'a';
arr[0] = 'a';
arr.push('c');
arr.push('d','e','f',123,4.5,'foodoir');
console.log(arr);
console.log(arr.length);//8 //向数组的首部添加一个或多个元素unshift()
arr.unshift(1,2,3);
console.log(arr);//1,2,3,a,c,d,e,f,123,4.5,foodoir
console.log(arr.length);//11

3、读取数组中元素

  arr[下标],同1

4、修改数组中的元素

  arr[下标]=值;同1

5、删除数组中元素

  delete arr[下标]

    注意:使用delete删除数组元素不会改变数组的length属性

  arr.pop():删除数组的元素

  arr.shift():删除数组开头的元素

  可以通过设置length属性,删除数组后面的元素

		//通过数组下标来删除数组中的元素
var arr = [1,2,3,'a','hello'];
console.log(arr);
delete arr[1];//删除数组中第二个元素
console.log(arr);//1,,3,a,hello
console.log(arr.length);//5数组的长度没变
//删除数组末尾的元素pop();
var arr = [1,2,3,4.5,'foodoir'];
var a = arr.pop();//弹出最后一个元素
console.log(a);//foodoir,此时数组中最后一元素为4.5
arr.pop();//再删除最后一个元素
console.log(arr);//结果为:1,2,3
console.log(arr.length);//3
//删除数组中的首部
var a = arr.shift();
console.log(a);//1
console.log(arr);//2,3
//通过设置length属性,删除数组后面的元素
var arr = [1,2,3,4,5,6];
arr.length = 3;//设置了数组的长度为3
//console.log(arr);//1,2,3
arr.length = 0;//将数组中所有的数据都删除
console.log(arr);//Array[0]

补充:有些资料上在使用数组的方法上提到了栈方法队列方法,这里我们也对之前的例子进行理解

栈方法:
  pop()删除并返回数组的最后一个元素
      push()向数组的末尾添加一个或更多元素,并返回新的长度。
队列方法  :
     shift()删除并返回数组的第一个元素
     push()向数组的末尾添加一个或更多元素,并返回新的长度
   unshift()向数组的开头添加一个或更多元素,并返回新的长度。
1、栈是一种LIFO(Last-In-First-Out,后进先出)的数据结构,也就是最新添加的项最早被移除。栈中项的插入(push)和移除,只发生在一个位置——栈的顶部。ECMAScript为数组提供了push()和pop()方法,可以实现类似栈的行为。
  push()方法可以接收任意数据的参数,把它们逐个添加到数组末尾,并返回修改后的数组长度。pop()方法从数组末尾移除最后一项,减少数组的length值
2、栈数据结构的访问规则是LIFO(后进先出),而队列数据结构的访问规则是FIFO(First-In-First-Out,先进先出)。队列在列表的末端添加项,从列表的前端移除项。push()方法是向数组末端添加项的方法,因此要模拟队列只需一个从数组前端取得项的方法——shift(),其能够移除数组中的第一个项并返回该项,同时数组的length-1。结合使用shift()和push()方法,可以像使用队列一样使用数组。
此外,ECMAScript还提供了unshift()方法,它能在数组前端添加任意个项并返回新数组的长度。因此,结合使用unshift()和pop()方法,可以从相反的方向来模拟队列,即在数组的前端添加项,从数组末端移除项

四、遍历数组

1、for循环遍历下标连续的数组

2、for-in遍历数组

3、通过forEach()遍历数组

语法:Array.forEach(function(value[,index[,array]]){函数体})

	//数组中如何进行遍历
//当索引连续时,可以用for循环遍历
var arr = ['a','b','c',123];
for(var i = 0 ; i<arr.length;i++){
console.log(arr[i]);//a,b,c,123
}
//当索引不连续时,可以用for/in循环
var arr1 = [];
arr1[1] = 'x';
arr1[22] = 'y';
arr1[333] = 'z';
for(var i in arr1){
console.log(arr1[i]);//x,y,z
}//这种方法遍历的是继承下来的属性,若不想遍历继承下来的属性可以用hasOwnProperty()函数
for(var i in arr1){
if(arr1.hasOwnProperty(i)){
console.log(arr1[i]);//x,y,z
}
}//这种方法遍历的不是继承下来的属性 //我们还可以通过forEach()方法来遍历数组
//语法:Array.forEach(function(value[,index[,array]]){函数体})
var arr2 = [1,2,3,4,5,6];
//方法一:
arr2.forEach(function(x){
console.log(x);
});1,2,3,4,5,6
//方法二:
function Test(element,index,array){
console.log('要处理的数组为:'+array);
console.log('索引:'+index+'--值为:'+element);
}
arr2.forEach(Test);

五、数组的常用方法

1、Array.join([delimiter])

  描述

    将数组中的值连接成字符串

  参数

    以指定分隔符连接,如果不指定,默认以,连接

  返回值

    返回连接之后的字符串

  注意

    Array.join()是string.split()方法的逆向操作

 小结:数组转换方法:join

在一般默认情况下,会以逗号分隔的字符形式返回数组项;而join方法可以使用不同的分隔符来构建字符串,join方法只接受一个参数,用作分隔符的字符串,然后返回所有包含数组项的字符串

2、Array.reverse()

  描述

    数组倒置

   返回值

  返回倒置之后的数组

3、Array.sort()

  描述

    数组排序函数

  参数

    如果不带参数调用sort,数组以字母顺序进行排序,升序

  返回值

    返回排序之后的数组

  注意

    如果数组中包含undefined元素,它们会被排到数组的尾部,比如:

      var a = [1,2,4,undefined,3,5];
             console.log(a.sort());//0 : 1 1 : 2 2 : 3 3 : 4 4 : 5 5 : undefined

小结:reverse()和sort()是数组中存在的两个可以用来重排序的方法

4、Array.concat(value,...)

  描述

    创建并返回一个新数组,数组中包含调用concat的原始数组的元素和concat的每个参数。

  返回值

    返回连接之后的新数组

  注意

    如果这些参数中的任何一个自身是数组,则连接的是数组的元素,而非数组本身

5、Array.slice(start[,end])

  描述

    返回数组中的部分

  参数

    start起始点

    end结束位置

  返回值

    返回数组中的部分

6、Array.splice(index , howMany[, element1[, ...[, elementN]]])

  描述

    添加或删除数组中的一个或多个元素

  参数

    index从数组的哪一位开始修改内容。如果超出了数组的长度,则自动从数组末尾开始添加内容;如果是负值,则表示从数组末位开始的第几位。

    howMany是整数,表示要移除的数组元素的个数。如果 howmany 是 0,则不移除元素。这种情况下,至少应添加一个新元素。如果 howmany 超出了 index 位之后的元素的总数,则从 index 向后至数组末尾的全部元素都将被删除(含第 index 位)。如果没有指定 howmany 参数(如上第二种语法,是 SpiderMonkey 的扩展功能),将会删除第 index 位之后的所有元素(不含第 index 位)

element1...要添加进数组的元素。如果不指定,则 splice 只删除数组元素。

  返回值

    由被删除的元素组成的一个数组。如果只删除了一个元素,则返回只包含一个元素的数组。如果没有删除元素,则返回空数组。

  注意

    如果添加进数组的元素个数不等于被删除的元素个数,数组的长度会发生相应的改变。

7、Array.push(value,...)

  描述

    像数组末尾添加一个或者多个元素

  参数

    添加的值

  返回值

    返回数组的长度

8、Array.pop()

  描述

    弹出数组的最后的元素

  返回值

    返回弹出的元素

9、Array.unshift(value,...)

  描述

    向数组开始添加一个或者多个元素

  参数

    添加的值

  返回值

    返回数组的长度

10、Array.shift()

  描述

    弹出数组开始的元素

  返回值

    返回弹出之后的值

 小结:这四种方法称为:栈和队列方法,

11、Array.map()

  描述

    返回一个由原数组中的每个元素调用一个指定方法后的返回值组成的新数组

  语法

    Array.map(callback)

  参数

    callback回调函数

    currentValue,callback的第一个参数,数组中当前被传递的元素

    index,callback的第二个参数,数组中当前被传递的元素的索引

    array,callback的第三个参数,调用map方法的数组

  注意

  map 方法会给原数组中的每个元素都按顺序调用一次 callback 函数

  callback 每次执行后的返回值组合起来形成一个新数组

  callback 函数只会在有值的索引上被调用,那些从来没被赋过值或者使用 delete 删除的索引则不会被调用

12、Array.filter()

  描述

    方法使用指定的函数测试所有元素,并创建一个包含所有通过测试的元素的新数组

  语法

    arr.filter(callback)

  注意

    filter 为数组中的每个元素调用一次 callback 函数,并利用所有使得 callback 返回 true 或 等价于 true 的值 的元素创建一个新数组

    callback 只会在已经赋值的索引上被调用,对于那些已经被删除或者从未被赋值的索引不会被调用。那些没有通过 callback 测试的元素会被跳过,不会被包含在新数组中。

13、Array.reduce()

  描述

    reduce方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终为一个值  

   语法

    arr.reduce(callback,[initialValue])

  参数

    callback

    previousValue,上一次调用返回的值或者是提供的初始值(initialValue)

    currentValue,数组中当前被处理的元素

    index,当前元素在数组中得索引

    array,调用reduce的数组

    initialValue,作为第一次调用callback的第一个参数

  注意

    reduce 为数组中的每一个元素依次执行回调函数,不包括数组中被删除或从未被赋值的元素,接受四个参数:初始值(或者上一次回调函数的返回值),当前元素值,当前索引,调用 reduce 的数组

    回调函数第一次执行时,previousValue 和 currentValue 可以是一个值,如果 initialValue 在调用 reduce 时被提供,那么第一个 previousValue 等于 initialValue ,并且currentValue 等于数组中的第一个值;如果initialValue 未被提供,那么previousValue 等于数组中的第一个值,currentValue等于数组中的第二个值。

14、Array.reduceRight()

  描述

    与reduce()方法的执行方向相反

15、Array.some()

  描述

    测试数组中的某些元素是否通过了指定函数的测试

  语法

    arr.some(callback)

  注意

    some 为数组中的每一个元素执行一次 callback 函数,直到找到一个使得 callback 返回一个真值(即可转换为布尔值 true 的值)

16、Array.every()

  描述

    测试数组的所有元素是否都通过了指定函数的测试。

  语法

    arr.every(callback)

  注意

    every 方法为数组中的每个元素执行一次 callback 函数,直到它找到一个使 callback 返回 falsy(表示可转换为布尔值 false 的值)的元素。如果发现了一个这样的元素,every 方法将会立即返回 false。否则,callback 为每一个元素返回 true,every 就会返回 true。callback 只会为那些已经被赋值的索引调用。不会为那些被删除或从来没被赋值的索引调用

17、Array.indexOf()

28、Array.lastIndexOf()

19、Array.isArray()

  描述

    检测某个值是否为数组

20、Array.toString()

  描述

    返回一个字符串,表示指定的数组及其元素。

  返回值

    返回一个字符串,表示指定的数组及其元素。

  注意:

    1、该方法的返回值与不使用任何参数调用join的方法一致,如[1,2,3].toString();//'1,2,3

    2、由于alert要接收字符串参数,它会在后台调用toString()方法,会得到与toString()方法相同的结果,如alert([1,2,3]);//1,2,3

21、Array.toLocaleString()

  toLocaleString()是toString()方法的本地化版本,他经常会返回到与toString()方法相同的结果

  如果数组中的某一项值为null或是undefined,该值在toLocaleString()和toString()方法返回的结果以空字符串表示,如:

    var a=[1,null,2,undefined,3];

    console.log(a.toLocaleString());//1,,2,,3

    console.log(a.toString());//1,,2,,3

  关于二者的区别,可以通过下面的例子来理解:

    toLocaleString 方法返回一个 String 对象,这个对象中包含了用当前区域设置的默认格式表示的日期。
    对于公元 1601 和 1999 之间的时间,日期格式要按照用户的“控制面板”中“区域设置”来确定。
    F对于此区间外的其他时间,使用 toString 方法的默认格式。
    例如,同样是 3 月 21 日,在美国,toLocaleString 可能会返回 "03/21/08 01:02:03",而在欧洲,返回值则可能是 "21/03/08 01:02:03",因为欧洲的惯例是将日期放在月份前面。
    toLocaleString 只是用来显示结果给用户;最好不要在脚本中用来做基本计算,因为返回的结果是随机器不同而不同的。

22、Array.valueOf()

  valueOf()方法返回数组对象本身

    var a=[1,2,3];

    console.log(a.valueOf());//[1,2,3]

    console.log(a.valueOf() instanceof Array);//true

小结:toString,toLocaleString和valueOf方法,都是属于对象的继承方法!

它们的具体使用方法如下:

		//数组中常用的方法
var arr = ['a','b','c','d','e'];
//join
var a = arr.join();//a,b,c,d,e 默认为","
a = arr.join(",");//a,b,c,d,e
a = arr.join("");//abcde 修改为空
console.log(a); //reverse反转
a = arr.reverse();
console.log(a); //sort()排序
var arr1 = ['a','b','c','A','B','C'];
var a = arr1.sort();
console.log(a);//A,B,C,a,b,c 默认排序是按照码排序
//也可以自己指定排序的顺序
var arr2 = [1,2,3,11,15,20,23,30];
var a = arr2.sort();
console.log(a);//1,11,15,2,20,23,3,30
var a = arr2.sort(function(a,b){
return a-b;
});
console.log(a);//1,2,3,11,15,20,23,30
var a = arr2.sort(function(a,b){
return b-a;
});
console.log(a);//30,23,20,15,11,3,2,1 var users = [
{name:'foodoir',age:21},
{name:'hello',age:33},
{name:'world',age:44},
{name:'jake',age:55},
];
// console.log(users);
users.sort(function(a,b){
if(a.name>b.name) return 1;
if(a.name<b.name) return -1;
return 0;
});
// console.log(users);
for(var i in users){
console.log(users[i]['name']);//注意是访问的数组里面的name属性方法是users[i]['name']
} //concat数组的链接
var arr = [1,2,3];
var a = arr.concat('a');//1,2,3,a
var a = arr.concat([4,5,6]);
var a = arr.concat([4,[5,['a','b','c']]]);
console.log(a); //slice()
var arr = ['a','b','c','d','e','f','g','h','i'];
var a = arr.slice(0,3);
console.log(a);//a,b,c
var a = arr.slice(0,-2);
console.log(a);//a,b,c,d,e,f,g
var a = arr.slice(-5,-3);//
console.log(a);//e,f
var a = arr.slice(-5,3);//不存在
console.log(a);//e,f
var a = arr.slice(-5,0);//不存在
console.log(a);//e,f
var a = arr.slice(4);//表示从左边第五个开始,一直到数组末尾
console.log(a);//e,f,g,h,i
var a = arr.slice(-4);//表示从右边第四个开始,一直到数组末尾
console.log(a);//f,g,h,i
console.log(arr);//原数组并没有变化 //splice
var arr = ['a','b','c','d','e','f','g','h','i'];
console.log(arr.length);//9
var a = arr.splice(0,1);
console.log(a);//a
console.log(arr);//b,c,d,e,f,g,h,i
console.log(arr.length);//8
//此种方法将数组中的值取出来了,导致数组长度减少
var a = arr.splice(5);
console.log(a);//g,h,i
console.log(arr);//b,c,d,e,f
console.log(arr.length);//5
var a = arr.splice(0,2,'!','?','%');
console.log(a);//b,c 截取的值为b,c ,并且在b,c 的基础上,加上了!,?,%,
console.log(arr);//!,?,%,d,e,f
console.log(arr.length);//6 //map
var arr = [1,2,3,4,5];
var a = arr.map(function(x){
return x*x;
});
console.log(a);//1,4,9,16,25
var arr = ['a!','b!','c','d','e!'];
var a = arr.map(demo);
function demo(x){
return x.replace(/!/g,'?').toUpperCase();//将!改为?,将小写变为大写
}
console.log(a); //filter过滤
var arr = [1,2,4,8,16,32,22];
var a = arr.filter(function(x){
return x<=10;
});
console.log(a);//1,2,4,8 只输出值小于10 的
var arr1 = [1,2,4,8,16,32,21,true,false,null,undefined];
var a1 = arr1.filter(function(x){
//过滤掉奇数
return x%2 == 0;
});
console.log(a1);//0:2 1:4 2:8 3:16 4:32 5:false 6:null length : 7
var arr1 = [1,2,4,8,16,32,21,true,false,null,undefined];
var a1 = arr1.filter(function(x){
//过滤掉null/undefined
return x!== null && x!==undefined;
});
console.log(a1);//1,2,4,8,16,32,21,true,false //reduce
var arr = [1,2,3,4,5];
var a = arr.reduce(function(a,b){
return a+b;
});
console.log(a);//15
var a = arr.reduce(function(a,b){
return a+b;
},10); //传入初始值10
console.log(a);//25 //every和some
var age = [11,22,33,44,55];
//every,当数组中所有的值都满足条件时,返回true,否则返回false
var a = arr.every(function(x){
return x>=18;
});
console.log(a);//false
//若将age里面的11改为18,则为true
//some ,当数组中只要有值满足条件,就返回true
var b = arr.some(function(y){
return y<18;
});
console.log(b);//true //indexOf,a最先出现的位置
var arr = ['a','b','c','d','e'];
var res = arr.indexOf(a);
console.log(res);//没有的话,返回的是-1
var res = arr.indexOf('a');
console.log(res);//有的话,返回的是该值对应数组中的索引
var arr = ['a','b','c','d','e','a','bc','a'];
var res = arr.indexOf('a',2);//表示从第二个开始索引
console.log(res);//5
//lastIndexOf(),a最后出现的位置
var res = arr.lastIndexOf('a');
console.log(res); //Array.isArray()
var arr = ['a','b','c','d','e'];
console.log(Array.isArray(arr));//true
console.log(Array.isArray([]));//true
console.log(Array.isArray({}));//false,空的对象不是数组,
//数组是对象,但是对象不是数组 //toString
var arr = ['a','b','c','d','e'];
console.log(arr.toString());//a,b,c,d,e
console.log(arr.join());//a,b,c,d,e