JavaScript数据类型 - Array类型

创建数组一

在JavaScript中,Array类型也是相当常用的一种类型。而且JavaScript中的数组与其他语言中的数组有着很大的区别。虽然js中的数组与其它语言中的数组都是有序列表,但与其它语言不同的是,js中的数组的每一项都可以保存任何类型的数据。也就是说数组的第一个值可以是字符串,第二个值可以是数值,第三个值可以是布尔值、对象等等。并且js数组可以动态调整大小。

创建数组的基本方式有两种。第一种是使用Array构造函数,如下所示:

var colors = new Array();

如果预先知道数组要保存的项目数量,可以给构造函数传递该数量,该数量会自动变成length属性的值,即数组的长度。看下面的例子:

var colors = new Array(20);//创建一个长度为20的数组

也可以向Array构造函数传递数组中具体的项,如下所示:

var colors = new Array('red','pink','green');//创建了一个包含3个值的数组

当只给构造函数传递一个参数时就要注意了,因为如果传递的参数是一个数值,则会按照该数值创建包含给定项数的数组,即这个数值会变成数组的长度值。而如果传递的是其它类型的参数,则会创建包含这个值的长度为1的数组。如下示例:

var colors = new Array(3); //长度为3的空数组
var names = new Array("Alvin");//长度为1且包含一个值Alvin的数组

另外在使用Array构造函数时也可以省略new关键字,如下所示省略new关键字得到的结果是一样的:

var colors = Array(3); //长度为3的空数组
var names = Array("Alvin");//长度为1且包含一个值Alvin的数组

创建数组二

创建数组的第二种基本方式是使用数组字面量表示法。数组字面量由一对包含数组值方括号表示,多个数组项之间用逗号分隔,如下所示:

var colors = ['red', 'pink', 'green']; //创建一个包含3个字符串的数组
var names = []; //创建一个空数组

上面的代码中分别创建了一个长度为3且包含3个字符串的数组和一个空数组。

在读取和设置数组值时,要使用方括号并使用下标的形式进行访问或设置,下标从0开始。来看下面的例子:

var colors = ['red', 'pink', 'green'];
console.log(colors[1]); //pink

colors[0] = 'yellow'; //将第一个元素值更新为yellow
colors[3] = 'blue';//添加一个新的值 blue

方括号中的索引表示要访问的值。如果索引小于数组的长度,则返回对应的索引的值。在 这个例子中colors[0]会返回‘red’。设置数组的值也是一样,但是会替换掉指定索引位置的原来的值。如果设置某个值的索引超过了数组的长度,比如colors[3],数组就会自动增加到该索引值加1的长度。数组的长度保存在length属性中,这个属性始终返回0或更大的值。如下代码所示:

var colors = ['red', 'pink', 'green'];
var names = [];

console.log(colors.length);//3
console.log(names.length); //0

数组的length属性很有特点,它不是只读的,因此通过设置这个属性,可以从数组的末尾移除项或添加项

var colors = ['red', 'pink', 'green']; //创建长度为3的数组
colors.length = 2; //设置数组的长度为2
console.log(colors[2]);//undefined

在上面的代码片段中,我们将数组的长度改为2后发现在访问数组的第3项值时就变成了undefined。如果将其length属性设置为大于数组项数的值,则新增的每一项都会取得undefined值。

判断一个对象是否是数组,可以用Array.isArray(obj)来判断。例如:

var colors = ['red', 'pink', 'green'];
console.log(Array.isArray(colors));// true

转换方法

toLocaleString()

toString()

valueOf()

在讲Object类型时,我们已经提到:所有对象都具有toLocaleString()、toString()和valueOf()方法。其中调用数组的toString()方法会返回由数组中每个值的字符串形式拼接而成的一个以逗号分隔的字符串。为了更深入理解,我们来看下面的例子:

var colors = ['red', 'pink', 'green'];
console.log(colors.toString()); // "red,pink,green"
console.log(colors.valueOf()); // "red,pink,green"
console.log(colors); // "red,pink,green"

上面的代码中,首先显示的调用了toString()和valueOf()方法,结果返回了一个由每个值的字符串形式组成的以逗号分隔的字符串。最后一句直接将数组传递给了console.log(),由于console.log()接收字符串参数,所以它会在后台调用toString()方法,由此会得到与显示调用toString()方法一样的结果。
另外我们还可以数组的join()方法来实现同样的效果,不同的是调用join()方法可以指定不同的分隔符,如下所示:

var colors = ['red', 'pink','green'];
console.log(colors.join(',')); //"red,pink,green"
console.log(colors.join('||')); // "red||pink||green"

栈方法

push() 从数组末尾添加

pop() 从数组默认删除

JavaScript数组也提供了一种让数组的行为类似于其他数据结构的方法。具体来说,数组可以表现的就像栈一样。栈是一种可以限制插入和删除想的数据结构。栈是一种LIFO(Last-In-First-Out,后进先出)的数据结构,也就是最后添加的项最先被移除。而栈中项的插入和移除(也叫推入和弹出)只发生在一个位置——栈的顶部。JavaScript中专门为数组提供了push()方法和pop()方法,用于实现类似栈的行为。

push()方法可以接收任意数量的参数,把它们逐个添加到数组的末尾,并返回修改后的数组的长度。而pop()方法则从数组的末尾移除最后一项,减少数组的长度,然后返回被移除的项。

var colors = []; //定义一个空数组
var len = colors.push("red","pink");//向数组中推入两个项red和pink并返回数组的新的长度
console.log(len); //2

len = colors.push('green'); //再添加一个新值green
console.log(len); //3 数组新的长度变为3


var item = colors.pop();
console.log(item); //green 移除数组的最后一项并返回
console.log(colors.length); //数组长度变为2

上面的代码中的数组可以看做是栈,push和pop都是数组默认的方法。首先我们调用push()方法把两个字符串推入到数组的末尾,并将返回的结果(数组的长度)保存到变量中,然后再推入一个新值,结果任然保存在变量中,此时数组的长度已经变为3。在调用pop方法时,它会返回数组的最后一项,即字符串green,此时数组的长度就变为2了。

另外还可以将栈方法与数组的其它方法连用,比如:

var colors = ['red', 'pink']; //创建一个长度为2,值为red和pink的数组

colors.push("green");//使用push方法向数组中添加一个新值green
colors[3] = 'blue'; //通过下标的形式向数组添加新值blue

console.log(colors.length); //4 数组长度变为4

var item = colors.pop(); //移除数组最后一项值 blue
console.log(item);// 返回blue

队列方法

shift() 从数组前端删除

unshift() 从数组前端添加

栈数据结构的访问规则是LIFO(后进先出),而队列数据结构的访问规则是FIOF(First-In-First-Out,先进先出)。队列在列表的末端添加项,而在列表的前端移除项。由于push是向数组末端添加项的方法,因此要模拟列队只需要一个从数组前端获取项的方法。那么数组也提供了这样一种方法——shift(),它能够移除数组中第一项并返回该项,同时数组长度减1。来看以下代码:

var colors = []; //创建一个空数组
var len = colors.push('red', 'pink');//数组中推入red和pink两项
console.log(len); //数组长度变为2

len = colors.push('green'); //再添加一项green,同时数组长度变为3

var item = colors.shift();//移除数组中第一项的值并返回
console.log(item);// red
console.log(colors.length); //2 数组长度又变为2

上面示例中,我们通过调用数组的push方法向数组中添加了3个值(red,pink,green),然后又调用数组的shift()方法移除了数组中的第一个值并返回给变量item,此时我们打印item输出值为red,这样印证了shift()方法是从数组的前端开始移除,与pop()方法恰好相反。

另外JavaScript中还为数组提供了一个unshift()方法,顾名思义,unshift()与shift()的用途相反:它能在数组的前端添加任意个项,并返回新数组的长度。因此可以通过unshift()和pop()方法,可以从相反的方向来模拟列队,即在数组的前端添加项,从数组的末端移除项,如下代码:

var colors = [];
var len = colors.unshift('red', 'green');
console.log(len); //2

len = colors.unshift('pink');

var item = colors.pop();
console.log(item);// green

上面的代码中由于是从前端推入值,所以最后推入的pink变为数组的第一项,而green变为最后一项,所以调用pop()方法我们得到的是green。

重排序方法

reverse() 反转

JavaScript中数组有两个用来排序的方法:reverse()和sort()方法。reverse方法会对数组的项进行反转。如下:

var values = [1,2,3,4,5];
values.reverse();
console.log(values);//输出5,4,3,2,1

这里数组的初始值是1,2,3,4,5。而调用了reverse()方法后,其值的顺序变成了5,4,3,2,1。很明显数组项的顺序已经被反转了。

sort() 排序

另外一个方法sort(),sort方法是按升序顺序对数组项进行排序,为了实现排序,sort方法会调用每个数组项的toString()方法,然后比较得到的字符串,以确定如何排序。即使数组的每一项都是数值,sort方法比较的仍然是字符串。

var values = [0, 1, 5, 10, 15];
values.sort();
console.log(values);// 0,1,10,15,5

可见,即使数组中值的顺序没有问题,但sort()方法也会根据字符串的结果改变原来的顺序。因为数值5虽然小于10,但在进行字符串比较时,"10"则位于"5"的前面,于是数组的顺序就被修改了。很明显这种排序方式在很多情况下都不是最佳方案。因此sort方法可以接收一个比较函数作为参数,以便我们指定哪个值位于哪个值的前面。

比较函数接收两个参数,如果第一个参数应该位于第二个参数之前则返回一个负数,如果两个参数相等则返回0,如果第一个参数位于第二个参数之后则返回一个正数。比较函数适用于大多数数据类型,只要将其作为sort方法的参数即可。看下面的代码:

function compare(value1, value2){
    if(value1 < value2){
        return -1;
    }else if(value1 > value2){
        return 1;
    }else{
        return 0;
    }
}

var values = [0,5,1,15, 10];
values.sort(compare);
console.log(values);//0,1,5,10,15

现在我们再来看,数组的顺序已经按照数值的大小进行排序了。那么如果想要降序排序,只需将value1和value2比较的返回值互换一下即可。

function compare(value1, value2){
    if(value1 < value2){
        return 1;
    }else if(value1 > value2){
        return -1;
    }else{
        return 0;
    }
}

var values = [0,5,1,15, 10];
values.sort(compare);
console.log(values);//15,10,5,1,0

tips:reverse()方法和sort()方法的返回值是经过排序后的数组。

对于数值类型或者其valueOf方法返回数值类型的对象类型,可以使用更简单的比较函数,只需要用第二个参数减去第一个参数即可,如下代码所示:

function compare(value1, value2){
    return value2 - value1;
}

操作方法

concat() 拼接

JavaScript为操作数组中的项提供了很多方法,其中,concat()方法可以基于当前数组中的所有项创建一个新的数组。具体来说,这个方法会先创建当前数组的一个副本,然后将接收到的参数添加到这个副本的末尾,最后返回新构建的数组。在没有给concat方法传递参数的情况下,它只是复制当前数组并返回副本。如果传递给concat方法的是一个或多个数组,则该方法会将这些数组中的每一项都添加到结果数组中,如果传递的不是数组,这些值就会被简单的添加到结果数组的末尾。来看下面的代码:

var colors = ['red', 'green', 'pink'];
var colors2 = colors.concat('yellow', ['black','blue']);

console.log(colors); //red,green,pink
console.log(colors2); //red,green,pink,yellow,black,blue

从上面的代码中不难看出得到的新数组colors2在原来数组colors的基础上添加了新的元素yellow、black和blue,其中yellow是以字符串的形式添加到新数组,而black和blue是以数组的形式concat到新的数组。

slice() 截取

另一个方法是slice(),它能够基于当前数组中的一个或多个项创建一个新数组。slice()方法可以接受一个或两个参数,即要返回项的起始和结束位置。在一个参数的情况下,slice()方法返回从该参数指定位置开始到当前数组末尾的所有项。如果有两个参数,该方法返回起始和结束位置之间的项,但不包括结束位置的项。这里需要注意的是,slice()方法不会影响原来的数组。看下面的例子:

var colors = ['red','green','blue','yellow','pink'];
var colors2 = colors.slice(1);
var colors3 = colors.slice(1,4);

console.log(colors2);//green,blue,yellow,pink
console.log(colors3);//green,blue,yellow

上面的代码中,首先我们创建了一个包含5中颜色的colors数组,接着我们调用了数组的slice方法并传入一个参数1,意思就是从数组的索引为1的项(第二项)开始截取直到数组的末尾,索引我们的得到的colors2的结果为:green、blue、yellow和pink。而第三句代码中我们同样对colors调用了slice方法,但这次我们传入两个参数1和4,意思就是从数组的索引为1的项开始截取,直到索引为4的项结束(但不包括索引为4的项),所以我们得到的colors3数组的值为:green、blue和yellow。

splice() 删除/插入/替换

接下来我们要介绍的splice()方法也算是数组中比较强大的方法了,这个方法有很多用法,如下:

  • 删除:可以删除数组中任意数量的项,调用时只需要传递两个参数即可:要删除的项的位置(索引)和要删除的项的数量。例如:splice(1,2)从数组中索引为1的项开始删除,删除两项。注意:这里第二个参数不是结束位置而是要删除的项数。
  • 插入:可以向指定位置插入任意数量的项,需要提供3个或更多参数:要插入的位置,第二个参数必须传0(因为上面我们介绍过,第二个参数代表的是要删除的项数,传0即不删除),第三个参数是要插入的项。当然也可以传入第四项,第五项等等任意多个。例如:splice(2,0,'black', 'grey')从当前数组的第二个位置开始插入black和grey。
  • 替换:其实替换跟上面的插入很类似只不过是把第二个参的0改为具体的项数,也就是说先删除然后再插入。可以向指定位置插入任意数量的项,且同时删除任意数量的项,同样也需要提供3个参数:起始位置,要删除的项数,和要插入的项数,其中插入的项数和删除的项数不一定要相等。例如:splice(2,1,'red', 'green'),删除数组中索引为2项,然后再从索引2开始插入red和green两个值

splice方法始终都会返回一个数组,该数组中包含从原始数组中删除的项(如果没有删除任何项,则返回一个空数组),来看下面的代码,展示了上述3中方式的用法:

//删除
var colors = ['red', 'green', 'pink'];
var removed = colors.splice(0, 1);//删除第一项
console.log(colors); //green,pink
console.log(removed);//red

//插入
removed = colors.splice(1,0,'yellow', 'orange');//从索引1开始插入两个值
console.log(colors);//green,yellow,orange,pink
console.log(removed);//返回空数组

//替换
removed = colors.splice(1,1, 'red','blue');//从索引1开始删除一个值,并插入2个值
console.log(colors);//green,red,blue,orange,pink
console.log(removed);//yellow

位置方法

indexOf() 

lastIndexOf()

es5中为数组提供了两个位置方法,indexOf()和lastIndexOf()。这两个方法都接收两个参数:要查找的项和表示查找起点位置的索引。其中indexOf()方法从数组的开头(索引0)开始向后查找,而lastIndexOf()方法则是从数组的末尾开始向前查找。

这两个方法都返回要查找的项在数组中的位置,如果没找到则返回-1。在比较第一个参数与数组中的每一项时,会使用全等操作符,也就是说要求查找的项必须严格相等(就像用===一样)。看下面的示例:

var nums = [1,2,3,4,5,4,3,2,1];

//从0向后查找返回索引
console.log(nums.indexOf(4));// 3
//从最后一项向前查找
console.log(nums.lastIndexOf(4));//5

//从索引4向后查找
console.log(nums.indexOf(4,4));// 5
//从索引4向前查找
console.log(nums.lastIndexOf(4,4));//3


var person = {name: 'Alvin'};
var people = [{name:'Alvin'}];

var morePeople = [person];
console.log(people.indexOf(person));//-1
console.log(morePeople.indexOf(person));//0

迭代方法

es5中为数组提供了5个迭代方法。每个方法都接收两个参数:要在每一项上运行的函数和运行函数的作用域对象(可选)——会影响this的值。传入这些方法中的函数会接收3个参数:数组项的值、该项在数组中的索引和数组对象本身。

filter()

对数组中的每一项运行给定的函数,返回该函数会返回true的项组成的数组。例如:返回一个所有数值都大于2的数组。

var nums = [1,2,3,4,5,4,3,2,1];

var res = nums.filter(function(value,index,arr){
    return value > 2;
});

console.log(res);// [3,4,5,4,3]

forEach()

对数组中的每一项运行给定的函数,没有返回值。本质上与使用for循环迭代数组一样。例如:

var nums = [1,2,3,4,5,4,3,2,1];

nums.forEach(function(value,index,arr){
    //执行某些操作
});

map()

对数组中的每一项运行给定的函数,返回每次函数调用的结果组成的数组。例如:给数组的每一项都乘以2 ,然后返回每一项相乘后的数组。

var nums = [1,2,3,4,5,4,3,2,1];

var res = nums.map(function(value,index,arr){
    return value * 2;
});

console.log(res);// [2,4,6,8,10,8,6,4,2]

every()

对数组中的每一项运行给定的函数,如果该函数对每一项都返回true,在返回true。

var nums = [1,2,3,4,5,4,3,2,1];

var every = nums.every(function(value,index,arr){
    return value > 2;
});

console.log(every); //false

some()

对数组中的每一项运行给定的函数,如果该函数对任意一项返回true,则返回true。

var nums = [1,2,3,4,5,4,3,2,1];

var every = nums.some(function(value,index,arr){
    return value > 2;
});

console.log(every); //true

上面这些方法都不会修改数组中包含的值。在这些方法中,最相似的是every()和some(),它们都用于查询数组中的项是否满足某个条件。对every()来说,传入的函数必须对每一项都返回true,这个方法才会返回true,否则返回false。而some()方法则只要传入的函数对数组中的某一项返回true,就会返回true。

返回值总结

  • filter()返回符合条件的项组成的新数组,如过滤大于2的项
  • map()返回对数组项操作后组成的数组,如给每项乘以2
  • forEach()原理与使用for循环一样,没有返回值
  • every()只返回true或false
  • some()只返回true或false

缩小方法

reduce()

reduceRight()

es5中还提供了两个缩小数组的方法:reduce()和reduceRight()。这两个方法都会迭代数组的所有项,然后构建一个最终的返回值。其中reduce方法从数组的第一项开始,逐个遍历到最后,而reduceRight从数组的最后一项开始向前遍历到第一项。

这两个方法都接收两个参数:一个在每一项上调用的函数和作为缩小基础的初始值(可选)。传给这两个方法的函数接收4个参数:前一个值、当前值、项的索引和数组对象。这个函数返回的任何值都会作为第一个参数自动传给下一项。第一次迭代发生在数组的第二项上,因此第一个参数是数组的第一项,第二个参数就是数组的第二项。

使用reduce()方法可以执行求数组中所有值之和的操作,例如:

var values = [1,2,3,4,5];

var sum = values.reduce(function(prev,cur,index,arr){
    return prev + cur;
});

console.log(sum);//15

第一次执行回调函数,prev是1,cur是2,第二次,perv是3(1加2的结果),cur是3(数组的第三项)。这个过程会持续到把数组中的每一项都访问一遍,最后返回结果。

reduceRight的作用类型只不过是方向相反而已。

var values = [1,2,3,4,5];

var sum = values.reduceRight(function(prev,cur,index,arr){
    return prev + cur;
});

console.log(sum);//15

这个例子中,第一次执行回调函数,prev是5(数组最后一项),cur是4(倒数第二项)。最终结果是一样的。

无论是使用reduce还是reduceRight,主要取决于从哪边开始遍历数组,除此之外它们完全形同。

以上就是JavaScript中关于数组操作的一些方法。

猜你喜欢

转载自blog.csdn.net/lixiaosenlin/article/details/108337913