探索JavaScript数组奥秘
一 概述
javascript数组同后端语言一样,具有它自己的数据结构,归根结底,这种数据结构,本质就是一种集合。
在后端语言中(如java,.net等),数组是这样定义的:数组是用来存储相同数据类型的集合。这个定义,“相同数据类型”6个字限制了数据只能存储相同的数据类型,如int[]数组只能存储数字,而不能存储字符串,如下定义方式,是错误的,因为string
不属于整型
int[] arr = { 10, 20,"string" };
然而,在javascript中,数组的定义却是非常宽松的,这也决定了其能存储一切数据的特点。javascript数组具有如下特点
特点1:存储相同基本数据类型的数据;
特点2:存储不同基本数据类型的数据;
特点3:存储对象
这三个特点,我们可归结为一句话:javascript存储一切对象,而不像后端语言那样,只能存储相同数据类型。除此之外,javascript数组还提供了很多丰富的操作方法。如下为常用的操作方法。
本篇文章将主要结合代码来论述javascript数组。
二 对数组的基本操作
(一)创建数组
第一种方式:构造函数方式
//第一种创建数组的方式:构造函数方式 var colors = new array();//未知数组长度 //var colors = new array(4);//已知数组长度 //var colors = new array('green', 'yellow', 'white', 'red');//创建数组同时,给数组赋值 //var colors = array();//在创建时,可以省略new关键字
第二种方式:字面量方式
//第二种创建数组方式:使用数组字面量 var colors = ['green', 'yellow', 'white', 'red']; var name = [];//创建空数组
(二)访问数组
访问数组,通过数组的下标来访问
//创建数组 var colors = ['green', 'yellow', 'white', 'red']; //输出索引值 for (var i = 0; i < colors.length; i++) { alert(colors[i]);//green,yellow,white,red }
提示:for...in...访问数组属性(索引),而不是数组属性值
//创建数组 var colors = ['green', 'yellow', 'white', 'red']; //输出数组索引 for (var propattr in colors) { alert(propattr);//0,1,2,3 }
(三)为数组添加元素
第一种方式:栈方式(后进先出,从数组尾部加入数据)
//创建数组 var colors = ['green', 'yellow', 'white', 'red']; //第一种方式:栈方式 colors.push("orange"); for (var i = 0; i < colors.length; i++) { alert(colors[i]);//green,yellow,white,red,orange }
第二种方式:队列方式(先进先出,从数组头部加入数据)
var colors = ['green', 'yellow', 'white', 'red']; colors.unshift('orange'); for (var i = 0; i < colors.length; i++) { alert(colors[i]);//orange,green,yellow,white,red }
(四)移除数组元素
第一种方式:栈方式(后进先出,从数组尾部移除数据)
//创建数组 var colors = ['green', 'yellow', 'white', 'red']; //从尾部弹出数据 colors.pop(); for (var i = 0; i < colors.length; i++) { alert(colors[i]);//green,yellow,white }
第二种方式:队列方式(先进先出,从数据头部移除数据)
//创建数组 var colors = ['green', 'yellow', 'white', 'red']; //从头部移除数据 colors.shift(); for (var i = 0; i < colors.length; i++) { alert(colors[i]);//yellow,white,red }
第三种方式:length方式(借助length属性可访问性来操作)
//创建数组 var colors = ['green', 'yellow', 'white', 'red']; //从尾部移除数据,与pop()一样 colors.length = 3; for (var i = 0; i < colors.length; i++) { alert(colors[i]);//green,yellow,white }
三 数组方法
(一)检测方法
数组检测方式,可通过typeof,instranceof和array.isarray()来检测。
(二)转换方法
所有对象都具有tolocalestring(),tostring()和valueof()三个方法,数组也如此。
1.tostring()
tostring()将数据的每个属性值转化为对应的字符串,然后再输出转换后的字符串值。
var colors = ['red','green','yellow']; alert(colors.tostring());//red,green,yellow
而下列代码与如上代码是一样的,因为alert()接收的是字符串,所以会在后台调用tostring()方法
var colors = ['red','green','yellow']; alert(colors);//red,green,yellow
2.valueof()
valueof()方法同tostring()方法一样,也是返回数组的字符串
var colors = ['red', 'green', 'yellow']; alert(colors.valueof());//red,green,yellow
3.tolocalestring()
tolocalestring()返回数组的字符串形式。
var colors = ['red', 'green', 'yellow']; alert(colors.tolocalestring());//red,green,yellow
4 三者之间关系
关系1:当不显示指出调用哪个方法时(tostring(),tolocalestring()和valueof()),默认调用每个属性的tostring();
关系2:当显示地指出调用哪个方法时,就调用每个属性的该方法;
关系3:关于valueof问题,暂留
var person1 = { tostring: function () { return "alan"; }, tolocalestring: function () { return "alan_beijing"; }, valueof: function () { return "valueof1"; } }; var person2 = { tostring: function () { return "alan1"; }, tolocalestring: function () { return "alan_beijing1"; } } var people = [person1, person2]; alert(people.tostring());//alan,alan1 alert(people.tolocalestring());//alan_beijing,alan_beijing1 alert(people.valueof());//alan,alan1 alert(people);//alan,alan1
(三)栈方法
栈是一种数据结构,其算法为:lifo(last input first out)后进先出,其两个核心方法为push()和pop();
1.push()
push()表示将数据压入栈中,且放在栈的最后位置,即从栈的尾部压入数据。对于数组,则在数组的尾部加入数据,操作的顺序为:先把数组length+1,再压入数据。
var arr = [10, 20, 30]; arr.push('新加入的数据'); alert(arr.tostring());//10,20,30,新加入的数据
2.pop()
push()表示将数据从栈中弹出,且从栈的最后位置弹出。对于数组,则在数组的尾部弹出数据,操作的顺序为:先弹出数据,再数组length-1
var arr = [10, 20, 30]; arr.pop(); alert(arr.tostring());//10,20
(四)队列
队列是一种数据结构,其算法为:fifo(first input first out)后进先出,其两个核心方法为unshift()()和shift();
1.unshift()
unshift()表示从队列头部加入数据。对于数组,则从数组索引最小位置加入数据,操作顺序为:先将数length+1,再将当前数组属性值往后移动1个位置,最后将新数据添加到索引0处。
var arr = [10, 20, 30]; arr.unshift(40); alert(arr.tostring());//40,10,20,30
2.shift()
shift()表示从队列头部移除数据。对于数组,则从数组索引最小位置移除数据。
var arr = [20, 30]; arr.shift(); alert(arr.tostring());//30
(五)排序方法
在js数组中,两个重要的重排序方法:reverse()和sort()
1.reverse()
reverse(),顾名思义,逆序方法。
var arr = [1,2,3,4,5]; alert(arr.reverse());//5,4,3,2,1
2.sort()
sort()是比较灵活的排序方法了,支持自定义排序规则,默认排序为升序
默认为升序
var arr = [3, 1, 2, 5, 4]; alert(arr.sort());//1,2,3,4,5
自定义排序规则
var arr = [3, 1, 2, 5, 4]; alert(arr.sort(compare));//1,2,3,4,5 //自定义排序规则:正序 function compare(value1, value2) { if (value1 > value2) { return 1; } else if (value1 < value2) { return -1; } else { return 0; } }
(六)位置方法
js数组提供了两个位置方法:indexof()和lastindexof()
indexof()表示首次满足条件的位置;而lastindexof()则表示最后满足条件的位置
var arr = [20, 30,20,40,10]; alert(arr.indexof(20)); //0 alert(arr.lastindexof(20));//2
(七)迭代方法
ecmascript5提供了5个迭代方法:every(),filter(),foreach(),map()和some()
这个五个方法,均接收2个参数。
1.every()
对数组中的每项运行给定函数,如果该函数对每一项都返回ture,则返回true,否则返回false.
//every var num = [1, 2, 3, 4, 5, 4, 3, 2, 1]; var everyresult = num.every(function (item, index,array) { return item>2 }); alert(everyresult);//fasle
2.some
对数组中的每项运行给定函数,如果该函数对任意一项返回ture,则返回true,否则返回false
//some var num = [1, 2, 3, 4, 5, 4, 3, 2, 1]; var someresult = num.some(function (item, index, array) { return item > 2; }); alert(someresult);//true
3.filter
对数组中的每项运行给定函数,返回该函数会返回true的项组成的数组
//filter var num = [1, 2, 3, 4, 5, 4, 3, 2, 1]; var filterresult = num.filter(function (item, index, array) { return item > 2; }); alert(filterresult);//3,4,5,4,3
4.map
对数组中的每项运行给定函数,返回每次函数调用的结果组成的数组
//map var num = [1, 2, 3, 4, 5, 4, 3, 2, 1]; var mapresult = num.map(function (item, index, array) { return item * 2; }); alert(mapresult);//2,4,6,8,10,8,6,4,2
5.foreach
对数组中的每项运行给定函数。注意,该方法没返回值
//foreach num.foreach(function (item, index, array) { //执行想要执行的操作 });
(八)求和方法
ecmascript提供了2个缩减方法:reduce()和reduceright()
reduce和reduceright,相当于.net的斐波拉列数列,计算算法为:f(n)=f(n-1)+f(n-2);
1.reduce
reduce计算数组时,按照从左到右的顺序
var values = [1, 2, 3, 4, 5]; var sum = values.reduce(function (prev, cur, index, array) { return prev + cur; }); alert(sum);//15
2.reduceright
reducetight计算数组时,从右到左顺序
var values = [1, 2, 3, 4, 5]; var sum1 = values.reduceright(function (prev, cur, index, array) { return prev + cur; }); alert(sum1);//15
(九)其他方法
ecmascript为数组操作提供了很多方法,如concat()和slice()
1.concat()
concat()方法是将两个对象合并,从而生成新对象,合并同时,不会改变原来对象的值,只是做简单的拷贝
var color1 = ['red', 'green', 'yellow']; var color2 = ['white', 'blue']; //添加数组 var concatcolor = color1.concat(color2); alert(concatcolor);//red,green,yellow,white,blue //添加单个值 var concatsingelcolor = color1.concat('orange'); alert(concatsingelcolor);//red,green,yellow,orange //不添加值,只是简单copy var concatcolor1 = color1.concat(); alert(concatcolor1);//red,green,yellow
2.slice
slice()方法用于从目标数据中截取新数据,不会改变被截取对象的值。
var color1 = ['red', 'green', 'yellow']; //不传递参数:表示截取整个数组 var color2 = color1.slice(); alert(color2);//red,green,yellow //传递一个参数:表示从该位置处开始截取数据,直到数组最后一个数 var color3 = color1.slice(1); alert(color3);//green,yellow //传递2个参数:第一个参数表示从该位置开始截取,第二个参数减1表示所截数据的最后位置 var color4 = color1.slice(1, color1.length); alert(color4);//green,yellow
四 参考文献
【01】javascript 高级程序设计(第三版) (美)nicholas c.zakas 著 李松峰 曹力 译
【02】javascript 权威指南 (第6版) david flanagan 著