Javascript数组小结
- Javascript将指定的数字索引值转换成字符串——索引值1变成“1”——然后将其作为属性名来使用。
- 数组的length修改后,数组中大于设定值的元素将被删除
- 数组的添加删除:
1) 修改length属性值(删除)
2) push、pop在数组的尾部进行插入、删除操作并返回操作元素;unshift和shift()在数组的首部进行插入、删除操作
3) delete可以删除数组元素,但它不会改变数组的length属性,只是将该值置空。
4) splice()是一个通用的方法来插入,删除或替换数组元素。
4.Object.keys(obj):获取对象所有键值
5.遍历数组需要注意的问题
1) 排除null,undefined和不存在元素
for(var i=0;i<arr.length;i++){
if(!arr[i]) continue;
//循环体
}
2) 只排除undefined和不存在元素
for(var i=0;i<arr.length;i++){
if(arr[i]===undefined) continue;
//循环体
}
3) 只想跳过不存在元素,而仍然要处理存在的undefined元素
for(var i=0;i<arr.length;i++){
if(!(i in a)) continue;
//循环体
}
4) 还可以使用for/in循环处理稀疏数组,循环每次将一个可枚举的属性名(包括数组索引)赋值给循环变量。不存在的索引将不会遍历到,然而for/in循环能够枚举继承的属性名,如加到Array.prototype中的方法。由于这个原因,在数组上不应该使用for/in循环,除非使用额外的检测方法来过滤不想要的属性。
for(var i in arr){
if(!arr.hasOwnProperty(i))continue;//跳过继承属性
//循环体
}
for(var i in a){
//跳过不是非负整数的i
if(String(Math.floor(Math.abs(Number(i))))!==i)continue;
//循环体
}
5) ECMAScript5还定义了其他遍历方式
Data.forEach(function(c){
//处理程序
};
6.数组的常用方法
1) Array.join(分隔符)和String.split(分隔符),按指定的分隔符将数组转换为字符串,或者相反
2) Array.reverse()将数组中的元素颠倒顺序,返回逆序数组。它是在原数组上进行操作的。
3) Array.sort()将数组中的元素排序并返回排序后的数组。当不带参数调用sort()时,数组元素以字母表顺序排序(如有必要将临时转化为字符串进行比较),如果数组中包含undefined元素,他们会被排到数组的尾部。为了按照其他方式而非字母表顺序进行数组排序,必须给sort()方法传递一个比较函数。该函数决定了它的两个参数在排好序的数组中的先后顺序。假设第一个参数应该在后,函数应该返回一个大于0的数值。并且,假设两个值相等(也就是说,他们的顺序无关紧要),函数应该返回0,因此,例如,用数值大小而非字母表顺序进行数组排序,代码如下:
var a=[33,4,1111,22];
a.sort();//字母表顺序:1111,222,33,4
a.sort(function(a,b){//数值顺序:4,33,222,1111
return a-b;//根据顺序,返回负数,0,正数
});
a.sort(function(a,b){return b-a;});
另一个数组元素排序的例子,也许需要对字符串数组执行不区分大小写的字母表排序,比较函数首先将参数转换为小写字符串,在开始比较。
4) Array.concat()方法创建并返回一个新数组,它的元素包括调用concat()的原始数组的元素和concat()的每个参数。如果这些参数中的任何一个自身是数组,则连接的是数组的元素,而非数组本身。但要注意,concat()不会递归扁平化数组的数组。concat也不会修改调用的数组。
var a=[1,2,3];
a.concat(4,5) //返回[1,2,3,4,5]
a.concat([4,5]) //返回[1,2,3,4,5]
a.concat([4,5],[6,7]) //返回[1,2,3,4,5,6,7]
a.concat(4,[5,[6,7]]) //返回[1,2,3,4,5,[6,7]]
5) Array.slice()方法返回指定数组的一个片段或子数组。它的两个参数分别指定了片段的开始和结束的位置。返回的数组包含第一个参数指定的位置和所有和所有到但不包含第二个参数指定的位置之间的所有数组元素。如果只指定一个参数,返回的数组将包含从开始位置到数组结尾的所有元素。如果参数中出现负数,它表示相对于数组中最后一个元素的位置。该函数不对原数组进行操作。
6) Array.splice():方法是在数组中插入或删除元素的通用方法。不同于slice()和concat(),splice()会修改调用数组。splice()能够从数组中删除元素、插入元素到数组中或者同时完成这两种操作。eg:arr.splice(2,2,[1,2],3];//在2位置删除两个元素,并添加[1,2],3两个元素。
7) Array.push()、Array.pop():在数组尾部添加(可以为多个,数组当整体对待)、删除一个元素。
8) Array.unshift()和Array.shift():在数组头部插入(可以为多个,当有多个元素时会整体对待)、删除元素。
9) toString()和toLocaleString():主要区别在于后者会受本地控制面板里设置的时区的影响。
7.ECMAScript5中数组的方法
1) Array.forEach(value,index,arr):遍历数组中的每个元素,参数依次是遍历中数组的值,数组索引、数组。这个函数的缺点是无法在所有元素都传递给调用的函数之前终止遍历。
2) Array.map():方法将调用的数组的每个元素传递给指定的函数,并返回一个新数组,它包含该函数的返回值。map()返回的是新数组,它不修改调用的数组。如果是稀疏数组,返回的也是相同方式的稀疏数组:他们有相同的长度,相同的缺失元素。
3) Array.filter()方法返回的数组是调用的数组的一个子集。传递的函数时用来逻辑判定的:该函数返回true或false。调用判定函数就像调用forEach()和map()一样。如果返回值为true或能转化为true的值,那么传递给判定函数的元素就是这个子集的成员,它将添加到一个作为返回值的数组中。注意,filder()会跳过稀疏数组中缺少的元素,它的返回数组是稠密的。因此可以用来压缩稀疏数组,
var dese=sparse.filter(function(){return true;});
4) Arrary.every()和Array.some()是数组的逻辑判定:他们对数组元素应用指定的函数进行判定,返回true或false,前者所有的为真,才为真,后者存在一个元素满足条件即返回真。
5) reduce()和reduceRight():方法使用指定的函数将数组元素进行组合,生成单个值。这在函数式编程中是常见的操作,也可以称为“注入”和“折叠”。举例说明它是如何工作的:
var a=[1,2,3,4,5];
var sum=a.reduce(function(x,y){return x+y;},0):数组求和
var product=a.reduce(function(x,y){return x*y;}1):数组求积
var max=a.reduce(function(x,y){return (x>y)?x:y;});
reduce需要两个参数,第一个执行化简操作的函数。化简函数的任务就是用某组方法把两个值组合或化简为一个值,并返回化简后的值。在上述例子中,函数通过加法,乘法或取最大值的放大组合两个值。第二个(可选)的参数是一个传递给函数的初始值。第一个参数是到目前为止的化简操作累积的结果。第一次调用函数时,第一个参数是一个初始值,它就是传递给reduce的第二个参数。在接下来的调用中,这个值就是上一次化简函数的返回值。在上面的第一个例子中,第一次调用化简函数时的参数是0和1。将两者相加并返回1。将两者相加并返回1.再次调用时的参数是1和2,它返回3。然后它计算3+3=6、6+4=10,最后计算1+5=15.最后的值是15,reduce返回这个值。
可能已经注意到了,上面三次调用reduce()时只有一个参数:没有指定初始值。当不指定初始值调用reduce()时,它将使用数组的第一个元素作为其初始值。这意味着第一次调用化简函数就使用了第一个和第二个数组元素作为其第一个和第二个参数。在上面求和与求积的例子中,可以省略初始值参数。
在空数组上,不带初始值参数调用reduce()将导致类型错误异常。如果调用它的时候只有一个值——数组只有一个元素并且没有指定初始值,或者有一个空数组并且指定一个初始值——reduce只是简单地返回那个值而不会调用化简函数。
reduceRight()的工作原理和reduce一样,不同的是,它按照数组索引从高到低(从右到左)处理数组,而不是从低到高。如果化简操作的优先顺序是从左到右,你可能想使用它,例如:
var a=[2,3,4]
//计算2^(3^4).乘方操作的优先顺序是从右到左
varbig=a.reduceRigth(function(accumulator,value){
returnMath.pow(value,accumulator);
});
注意,reduce()和reduceRight()都能接收一个可选的参数,它指定了化简函数调用时的this关键字的值。可选的初始值参数仍然需要占一个位置。如果想化简函数作为一个特殊对象的方法调用,请参看Function.bind()方法。
值得注意的是,上面描述的every()和some()方法是一种类型的数组化简操作。但是不同的是,他们会尽早终止遍历而不总是访问每一个数组元素。
为了简单起见,到目前为止,所展示的励志都是数值的,但数学计算不实reduce()和reduceRight()的唯一意图。
6) indexOf()和lastIndexOf():搜索整个数组中具有给定值的元素,返回找到的第一个元素的索引或者如果没有找到就返回-1。indexOf()从头至尾搜索,而lastIndexOf()则按相反方向的搜索,这两个函数不接受一个函数作为其参数。第一个参数是需要搜索的值,第二个参数是可选的:它指定数组中的一个索引,从哪里开始搜索,如果省略该参数,indexOf()从头开始搜索。而lastIndexO()从末尾开始搜索,第二个参数也可以是负数,它代表相对数组末尾的偏移量。
8.ECMAScript5可以通过Array.isArray()函数来判断对象是否为数组。eg
Array.isArray([])://true
Array.isArray({}):false
但ECMAScript5以前,要区分数组和非数组是非常困难的。typeof操作符在这里帮不上忙,对数组它返回“对象“(并且对于除了函数以外的所有对象都是如此)。instanceOf操作符只能用于简单的情形。
[] instanceof Array //true
({}) instanceof Array //false
使用instanceof的问题是在Web浏览器中有可能有多个窗口或窗体(frame)存在。每个窗口都有自己的Javascript环境,有自己的全局对象。并且,每个全局对象有自己的一组构造函数。因此一个窗体中的对象将不可能是另外窗体的实例。窗体之间的混淆不常发生,但这个问题足以证明instanceOf操作符不能视为一个可靠的数组检测方法。
解决方法是检查对象的类属性。对数组而言该属性的值总是Array,因此在ECMAScript3中isArray()函数的代码可以这样写:
varisArray=Function.isArray||function(o){
return typeof o===”object”&&
Object.prototype.toString.call(o)==”[objectArray]”;
};
//(此处曾经是BAT的考点)
实际上,此处类属性的检测就是ECMAScript5中Array.isArray()函数所做的事情。
9.数组的特性:
1) 当有新的元素添加到列表中时,自动更新length属性
2) 设置length为一个较小值将截断数组
3) 从Array.prototype中继承一些有用的方法
4) 其类属性为“Array”
10.Javascript数组方法是特意定义为通用的,因此它们不仅应用在真正的数组而且在类数组对象上都能正确工作。在ECMAScript5中,所有的数组方法都是通用的。在ECMAScript3中,除了toString()和toLocaleString()以外的所有方法也是通用的。(concat()方法是一个特例,虽然可以用在类数组对象上,但它没有将那个对象扩充进返回的数组中。)既然类数组对象没有继承自Array.prototype,那就不能再它们上面直接调用数组方法。尽管如此,可以间接地使用Function.call方法调用:
vara={‘0‘:‘a‘,‘1‘:‘b‘,‘2‘:‘c‘,length:3};
Array.prototype.join(a,‘+‘);
console.log(Array.prototype.join.call(a,‘+‘));
console.log(
Array.prototype.map.call(a,
function(x){
returnx.toUpperCase();
}
));
11.作为数组的字符串:在ECMAScript5(在众多最近的浏览器实现——包括IE8——早于ECMAScript5)中,字符串的行为类似于只读的数组。除了用charAt()方法来访问单个字符串以外,还可以使用方括号:
var t=‘test‘;
console.log(t.charAt(0));//"t"
console.log(t[1]);//"e"
可索引的字符串的最大好处就是简单,字符串的行为类似于数组的事实使得通用的数组方法可以应用到字符串上。例如:
var t=‘test‘;
console.log(Array.prototype.join.call(t,‘‘));//t e s t
需要注意的是:字符串是不可变值,故当把它们作为数组看待时,他们是只读的。如push()、sort()、reverse()和splice()等数组方法会修改数组,它在字符串上是无效的。不仅如此,使用数组方法来修改字符串会导致错误,出错的时候没有提示。