所有的索引都是属性名,但是只有在0~2(32)-2之间的整数属性名才是索引,所有的数组都是对象,可以为其创建任意名字的属性。但如果使用的属性是数组的索引,数组的特殊行为就是将根据需要更新它们的length属性值。
数组的添加:
1、通过索引赋值
var a=[];
a[0]="zero";
a[1]="one";
2、使用push方法在数组末尾增加一个或者多个元素
var a=[];
a[0]="zero";
a[1]="one";
a.push("three");
a.push("four","five");
console.log(a);
在数组尾部压入一个元素,还可以使用a[a.length]赋值
a[a.length]="seven";
unshift在数组的首部插入一个元素,并且将其他元素依次移到更高的索引处
delete删除数组元素和为其赋值undefined值类似,对一个数组元素使用delete不会修改数组的length属性,也不会将元素从高索引处移下来填充已经删除属性的空白
var a=[1,2,3]; delete a[1]; console.log(a[1]);//undefined console.log(1 in a);//false console.log(a.length);//3
pop 一次使减少长度1并返回被删除的元素
shif 从数组头部删除一个元素。和delete不同的是shift方法将所有元素下移到比当前索引低1的地方
splice是一个通用的方法来插入、删除、替换数组元素,它会根据需要修改length属性并移动元素到更高或者较低的索引处
数组遍历
var a={x:1,y:2}; var keys=Object.keys(a); var values=[]; for(var i=0,len=ksys.length;i<len;i++){ var key=keys[i]; value[i]=a[key]; } //如果要排除null undefined 和不存在的元素 for(var j=0;j<a.length;j++){ if(!a[i]) continue; } //只想跳过undefined和不存在的元素 for(var m=0;m<a.length;m++){ if(a[m]===undefined) continue; } //如果只想跳过不存在的元素而仍然要处理存在的undefined元素 for(var n=0;n<a.length;n++){ if(!(n in a)) continue; }
for/in可用循环处理稀疏数组。循环每次将一个可枚举的属性名(包括数组索引)赋值给循环变量。不存在的索引将不会遍历到
for(var index in sparseArray){
var vaule=sparseArray[index]
}
注意上面可以循环可枚举继承的属性名,所以一般不用
除非先过滤
for(var i in a){ if(!a.hasOwnProperty(i)){//跳过继承属性 continue; } } for(var i in a){//跳过不是非负整数的i if(String(Math.floor(Math.abs(Number(i))))!==i){ continue; } }
按照索引的顺序按个传递给定义的一个函数
var data=[1,2,3,4,5]; var sum=0; data.forEach(function(x){ console.log(x*x); });
Array.join方法将数组中所有元素都转化为字符串并连接在一起,可以指定一个可选的字符串在生成的字符串中来分隔数组的各个元素,如果不指定分隔符,默认使用逗号。
var data=[1,2,3,4,5]; console.log(data.join());//1,2,3,4,5 console.log(data.join(" "));//1 2 3 4 5 console.log(data.join(""));//12345 var b=new Array(10); console.log(b.join("-"));//---------
reverse 将数组中的元素颠倒顺序,返回逆序的数组
var data=[1,2,3,4,5]; var b=data.reverse(); console.log(b);//[5, 4, 3, 2, 1] console.log(data);//[5, 4, 3, 2, 1]
sort 当不带参数调用方法时,元素以字母表顺序排序(如有必要将临时转化为字符串比较),如果数组包含undefined元素,它们会被排到数组的尾部
给sort方法传递一个比较函数。该函数决定了它的两个参数在排好序的数组中的先后顺序。假设第一个参数应该在前,比较函数应该返回一个小于0的数值.反之,假设第一个参数应该在后,函数应该返回一个大于0的数值,并且,假设两个值相等,函数应该返回0
var a=[33,44,1111,222]; console.log(a.sort());//[1111, 222, 33, 44] console.log(a.sort(function(a,b){//[33, 44, 222, 1111] return a-b; })); console.log(a.sort(function(a,b){//[1111, 222, 44, 33] return b-a; }));
字符串数组执行不区分大小写的字母表排序
var test=["ant","But","cat","Dog"]; console.log(test.sort());//["But", "Dog", "ant", "cat"] console.log(test.sort(function(s,t){//["ant", "But", "cat", "Dog"] var a=s.toLowerCase(); var b=t.toLowerCase(); if(a<b) return -1; if(a>b) return 1; return 0; }));
concat 他的元素包括调用concat的原始数组的元素和concat的每个参数。如果这些参数中的任何一个自身是数组,则连接的是数组的元素而非数组本身,但要注意。concat不会递归扁平化数组的数组。也不会修改调用的数组。
var test=[1,2,3]; console.log(test.concat(4,5));//[1, 2, 3, 4, 5] console.log(test.concat(4,[5,6]));//[1, 2, 3, 4, 5, 6] console.log(test.concat([4,5]));//[1, 2, 3, 4, 5] console.log(test.concat([4,5],[6,7]));//[1, 2, 3, 4, 5, 6, 7] console.log(test.concat(4,[5,[6,7]]));//[1, 2, 3, 4, 5, [6,7]]
slice 同字符串的截取一样 返回的数组包含第一个参数指定的位置和所有到但不含第二个参数指定的位置之间的所有数组元素,如果参数中出现负数,它表示相对于数组中最后一个元素的位置,不会修改调用的数组
splice()的第一个参数指定了插入和(或)删除的起始位置,第二个参数指定了应该从数组中删掉的元素的个数,如果省略第二个参数,从起始点开始到数组中结尾的所有元素都将被删除。splice返回一个由删除元素组成的数组,或者如果没有则返回空数组
splice的前两个参数指定了需要删除的数组元素,紧随其后的任意个数的参数指定了需要插入到数组中的元素,从第一参数指定的位置开始插入
var a=[1,2,3,4,5]; a.splice(2,0,'a','b'); console.log(a);//[1, 2, "a", "b", 3, 4, 5] a.splice(2,2,[1,2],3); console.log(a);//[1, 2, [1,2], 3, 3, 4, 5]
注意,区别于concat,splice会插入数组本身而非数组的元素。
push方法在数组的尾部添加一个或者多个元素,并返回数组新的长度
pop则相反,它删除数组的最后一个元素,减少数组长度并返回它删除的值
两个方法都修改并替换原始数组而非生成一个修改新的数组
unshift在数组的头部添加一个或者多个元素,并将已存咋的元素移动到更高索引的位置来获得足够的空间,最后返回数组新的长度
shift删除数组的第一元素并将其返回,然后把所有随后的元素下移一个位置来填补数组头部的空缺
注意。当使用多个参数调用unshift时他的行为令人惊讶。参数是一次性插入的(像splice)而非一次一个 的插入。这意味着最终的数组中插入的元素的顺序和他们在参数列表中的顺序一致。假如元素是一次一个的插入,他们的顺序应该是反过来的。
数组的toString(),该方法将其每个元素转化为字符串(如有必要将调用元素的toString()方法)并且输出用逗号分隔的字符串列表,输出不包括方括号或者其他形式的包裹数组值的分隔符
console.log([1,2,3].toString());//1,2,3 console.log(["a","b","c"].toString());a,b,c console.log([1,[2,"c"]].toString());//1,2,c console.log([1,{x:2}].toString());//1,[object Object]
注意,这里与不使用任何参数调用join()方法返回的字符串是一样的。
em5 定义的新方法 第一个参数接收一个函数,并且对数组的每个元素(或一些元素)调用一次函数,如果是稀疏数组,对不存在的元素不调用传递的函数,在大多数情况下,调用提供的函数使用三个参数:数组元素 元素的索引 和数组本身。如果有第二个参数,则调用的函数被看作第二个参数的方法,也就是说,在调用函数时,传递进去的第二个参数作为它的this关键字的值来使用
forEach()方法从头至尾遍历数组,为每个元素调用指定的函数。如上所述,传递的函数作为forEach的第一个参数
var data=[1,2,3,4,5]; var sum=0; data.forEach(function(v){ sum+=v; }); console.log(sum);//15 data.forEach(function(v,i,a){ a[i]=v+1; }); console.log(data);//[2, 3, 4, 5, 6]
map方法将调用的数组的每个元素传递给指定的函数,并返回一个数组,它包含该函数的返回值。
var data=[1,2,3,4,5]; var b=data.map(function(v){ return v*v; }); console.log(b);//[1, 4, 9, 16, 25
但传递给map函数的函数应该有返回值。注意,map()返回的是新数组:它不修改调用的数组,如果是稀疏数组,返回的也是相同方式的稀疏数组:具有相同的长度,相同的缺失元素。
filter返回的数组元素是调用的数组的一个子集,传递的函数是用来逻辑判断的,该函数返回true或false。如果返回值为true或者能转化为true的值,那么传递给判定函数的元素就是这个子集的成员,它将被添加到一个作为返回值的数组中。
filter会跳过稀疏数组中缺少的元素,他的返回数组总是稠密的
压缩稀疏数组的空缺
var dense=sparse.filter(function(){
return true;
});
压缩空缺并删除undefined和null元素
a=a.filter(function(x){
return x!==undefined&&x!=null;
});
every()和some()方法是对数组的逻辑判定:它们对数组元素应用指定的函数进行判定,返回true或者false
every:当且仅当针对数组中的所有元素调用判定函数都返回true,它才返回true
some 当数组中至少有一个元素调用判定函数返回true,它就返回true;并且当且仅当数组中的所有元素调用判定函数都返回false,它才返回false
var a=[5,4,3,2,1]; console.log(a.every(function(x){ return x<10; }));//true console.log(a.every(function(x){ return x%2===0; }));//false console.log(a.some(function(x){ return x%2===0; }));//true console.log(a.some(isNaN));//false
注意,一旦every和some()确认该返回什么值他们就会停止遍历数组元素,在空数组上调用是,every返回true。some返回false
reduce和reduceRight使用指定的函数将数组元素进行组合,生成单个值。需要两个参数,第一个是执行话间操作的函数,任务是用某种方法把两个值组合或者化简为一个值,并返回化简后的值。第二(可选)的参数是一个传递给函数的初始值。第一次调用韩式时,第一个参数是一个初始值,它就是传递给reduce的第二参数,在接下来的调用中,这个值就是上一次化简函数的返回值。当不指定初始值调用reduce时,它将使用数组的第一个元素作为初始值。这意味着第一次调用化简韩式就是用了第一个和第二个数组元素作为第一个和第二个参数
var a=[1,2,3,4,5]; var sum=a.reduce(function(x,y){return x+y;},0); console.log(sum);//15 var product=a.reduce(function(x,y){ return x*y; },1); console.log(product);//120 var max=a.reduce(function(x,y){return (x>y)?x:y;}); console.log(max);//5
都接收一个可选的参数,它指定了化简函数调用时this关键值的值
function extend(o,p){ for(var prop in p){ o[prop]=p[prop]; } return o; } function union(o,p){ return extend(extend({},o),p); } var objects=[{x:1,a:1},{y:2,a:2},{z:3,a:3}]; var leftunion=objects.reduce(union); var rightunion=objects.reduceRight(union); console.log(leftunion);//{x: 1, a: 3, y: 2, z: 3} console.log(rightunion);// {z: 3, a: 1, y: 2, x: 1}
indexOf和lastIndexOf 搜索整个数组中具有给定值的元素,返货找到第一个元素的索引或者如果没有找到就返回-1.indexOf从头到尾,lastIndexOf则反方向。第一参数是需要搜索的值。第二个参数是可选的;它指定数组中的一个索引,从那里开始搜索,第二个也可以是负数,它代表相对数组末尾的偏移量
function findall(a,x){ var result=[]; var pos=0; var len=a.length; while(pos<len){ pos=a.indexOf(x,pos); if(pos===-1){ continue; } result.push(pos); pos++; } return result; } var data=[1,3,4,5,2,1,7,1]; console.log(findall(data,1));//[0, 5, 7]
判断数组类型
var isArray=Function.isArray||function(o){ return typeof o==="object"&&Object.prototype.toString.call(o)==="[object Array]"; }; console.log(isArray([]));//true console.log(isArray({}));//false
类数组对象 拥有一个数值length属性和对应非负整数属性的对象看作一种类型的数组
在em5中,所有的数组方法都是通用的,在em3中,除了toString和toLocaleString以外的所有方法都是通用的(concat方法是一个特例,虽然可以用在类数组对象上,但它没有将安格对象扩充进返回的数组中);既然类数组对象没有继承自Array.prototype,那就不能在它们上面直接调用数组方法,尽管如此,可以间接的使用Function.call方法调用
function isArrrayLike(o){ if(o&&typeof o==="object"&&isFinite(o.length&&o.length>=0&&o.length===Math.floor(o.length)&&o.length<4294967296)){ return true; } else return false; }
var a={"0":"a","1":"b","2":"c",length:3}; console.log(Array.prototype.join.call(a,"+"));//a+b+c console.log(Array.prototype.slice.call(a,0));//["a", "b", "c"] console.log(Array.prototype.map.call(a,function(x){ return x.toUpperCase(); }));//["A", "B", "C"]
Array.join=Array.join||function(a,sec){ return Array.prototype.join.call(a,sec); }; Array.slice=Array.slice||function(a,from,to){return Array.prototype.slice.call(a,from,to);}; Array.map=Array.map||function(a,f,thisArg){ return Array.prototype.map.call(a,f,thisArg); }; console.log(Array.join(a,"+")); console.log(Array.slice(a,0)); console.log(Array.m
ap(a,function(x){ return x.toUpperCase(); }));
不仅如此,字符串的行为类似数组的事实使得通用的数组方法可以应用到字符串上
var s="JavaScript"; console.log(Array.prototype.join.call(s," "));//J a v a S c r i p t console.log(Array.prototype.filter.call(s,function(x){ return x.match(/[^aeiou]/); }).join(""));//JvScrpt
注意,字符串是不可变值,故当把它们作为数组看待时,它们是只读的,如push、sort。reverse,splice等数组方法会修改数组,它们在字符串上是无效的
总结下:forEach(遍历) map(映射) filter(过滤) 检测(every some) 简化(reduce reduceRight)
搜索(indexOf laistIndexOf)