javascript 学习笔记-数组

javascript数组

概述

js数组是无类型的。数组内元素可以是任意类型。索引范围在0-2^32-2(4294967294,约为42.9亿多)。数组不一定是连续的,根据其是否连续又分为稀疏数组和非稀疏数组两类。每个数组都有length属性,反应数组的长度。

js数组是js对象的特殊形式,可理解为属性值大都为(除length外)数字的特殊对象,此外,js数组又添加了许多针对数组的方法如forEach()、indexOf()等,以及js数组属性独有的length。这样总结说来,可将js数组可看作有特定属性值(数值及length)和特有操作方法的特殊对象。

数组基本特性

  1. 访问未赋值及不存在的属性返回undefined
  2. 数组可以有非数值属性和负数属性,只是这些属性不由length维护,也就是说,length属性维护的是数组合法索引内的数组长度

看一些例子即可明白:


//定义了5个元素,第4个未赋值
var arr = [1,2,3,,5]; 
console.log(arr.length);  //5

//访问未赋值及未定义元素都返回undefined
console.log(arr[3]);   //undefined 
console.log(arr[100]); //undefined

//字符类型的数值也可访问到元素
console.log(arr[1]);  //2
console.log(arr['1']);  //2

//属性为负值或非数值
arr[-2]=1;
arr['a']='b';
//仍能读取
console.log(arr[-2]);  //1
console.log(arr['a']); //b

//长度仍为5,说明非法索引的添加没有改变length属性
console.log(arr.length); //5

数组创建除使用字面量外,还可使用构造函数var arr = new Array(),效果与var arr = []相同,所以一般还是使用字面量较简单。

length属性值是可变的,修改length值可扩充或删减数组

var arr2 = [1,2,3,4,5];
arr2.length=10;
console.log(arr2,arr2.length); //[ 1, 2, 3, 4, 5, , , , ,  ]  10
arr2.length=3;
console.log(arr2,arr2.length);  //[ 1, 2, 3 ] 3

数组方法

Aarray.prototype定义了大量针对数组元素操作的方法,任何数组对象都可以直接使用它们。

添加、删除方法

总的看来,js数组的添加删除函数大概有:

  • push()和pop() :在数组尾部添加、删除一个或多个元素
  • unshift()和shift():在数组头部添加、删除一个或多个元素
  • splice() : 在数组添加、删除元素的通用方法,即可添加,也能删除。

push(pop)、unshift(shift)方法在数组的指定位置添删函数,用法也较为简单。而splice方法则要灵活的多。

1.push()

准确来说,该方法的声明应该类似为integer push(a ...),入参为0个或多个元素,返回值为新数组的长度。

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

//在数组尾部添加新元素,并返回数组长度。
console.log(arr.push(0),arr); //6 [ 1, 2, 3, 4, 5, 0 ]

//在数组尾部添加多个元素
console.log(arr.push(1,2,3),arr); //9 [ 1, 2, 3, 4, 5, 0, 1, 2, 3 ]

//即使添加的是数组,仍看作一个元素
var sub = [7,8,9];
console.log(arr.push(sub),arr); //10 [ 1, 2, 3, 4, 5, 0, 1, 2, 3, [ 7, 8, 9 ] ]

//表示添加0个元素
console.log(arr.push(),arr); //10 [ 1, 2, 3, 4, 5, 0, 1, 2, 3, [ 7, 8, 9 ] ]

2.pop()

pop()删除数组尾最后一个元素,并返回被删除元素,声明类似于integer pop(),无入参,即其只能删除最后一个元素。

console.log(arr); // [ 1, 2, 3, 4, 5, 0, 1, 2, 3, [ 7, 8, 9 ] ]
console.log(arr.pop()); //[7,8,9]
console.log(arr.pop())  //3
console.log(arr,arr.length); // [1, 2, 3, 4, 5, 0, 1, 2 ] 

3.unshift()及shift()

这两个方法与push()、pop()很相似,只是他们添加、删除的元素在数组首部,注意:调用unshift或shift后,数组其他元素将全部后移,索引将发生改变

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

//unshift()参数、返回值与push()类似,只是作用于数组头
console.log(arr.unshift(1,2,3),arr); //8 [ 1, 2, 3, 1, 2, 3, 4, 5 ]

//shift()参数、返回值与pop()类似,只是作用于数组头
console.log(arr.shift(),arr) // 1 [ 2, 3, 1, 2, 3, 4, 5 ]

4.splice()

splice()方法可同时添加、删除数组,被当作数组添加删除的通用方法。声明类似于splice(index,delCount,e...)。参数含义如下,返回删除元素组成的数组(未删除则为[])。

  • index :添加或删除的索引位置(必填)
  • delCount:删除元素的个数(选填,若为空则删除index后所有元素)
  • 要添加的元素,可为0个或多个(选填)
var arr = [1,2,3,4,5];

console.log(arr.splice(2, 2, 0,0,0)); //[3,4]

console.log(arr); //[ 1, 2, 0, 0, 0, 5 ]

反转、拼接、分片及排序

针对数组操作的一般方法js数组也都有提供,这些方法大都能见其名,只其义。需注意的是有些方法改变原数组而有些不。

string join([separator]); //使用指定分割符将数组分割为字符串,不指定则使用","(逗号),此方法显然不影响原数组。

array concat(item ...); //连接另一个数组并返回新数组,不会修改源数组

array slice(from,to); //如其名,返回原数组从索引from(包括)到to(不包括)的子数组序列,不修改源数组。

array reverse(); //将数组元素全部颠倒顺序。 改变原数组

array sort(); //按顺序排序返回排序后的数组

演示:

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

//以下两种方式结果一致,即js权威指南所言,
//cancat()不会递归扁平化数组的数组
console.log(arr.concat(1,2,3));   //[ 1, 2, 3, 4, 5, 1, 2, 3 ]
console.log(arr.concat([1,2,3]));  //[ 1, 2, 3, 4, 5, 1, 2, 3 ]

//包括第一个参数不包括第二个
console.log(arr.slice(2,4)); // [ 3, 4 ]

console.log(arr.join());  // 1,2,3,4,5
console.log(arr.join('-')); // 1-2-3-4-5

//reverse()改变了原数组
console.log(arr.reverse()); // [ 5, 4, 3, 2, 1 ]
console.log(arr); // [ 5, 4, 3, 2, 1 ]

//sort()改变了原数组
console.log(arr.sort()); //[ 1, 2, 3, 4, 5 ]
console.log(arr); //[ 1, 2, 3, 4, 5 ]

参数为函数的方法

ECMAScript5添加了若干诸如遍历、过滤等更加简洁的新方法,这些新方法大都可以传递函数作为参数,也就是所谓的函数式编程。

这些函数一般第一个参数为函数,且该数组每个元素都会调用一次该函数,函数提供了3个参数:当前数组元素、当前索引及数组本身,可根据需要使用。

举个例子就明白了:

forEach()

该方法从头至尾遍历数组。声明类似于forEach(func(e,i,arr))

var arr = [4,3,2,1];
// 遍历
var a = arr.forEach( function(element) {
    console.log(element); // 4 3 2 1    
});
//无返回值
console.log(a); // undefined 

//遍历时为每个元素加1
arr.forEach( function(element, index,array) {
    array[index]=element+1;
});
console.log(arr); // [ 5, 4, 3, 2 ]

其他类似方法参数与forEach()一致,直接说用法吧

其他方法

//对每个元素执行一次特定操作,返回修改后的数组
//如上例使用forEach()对数组每个元素的加一操作,它更适合。
map();

//过滤掉不符条件的元素,返回过滤后的数组。
//其返回的数组总是非稀疏数组
filter();

//对数组进行逻辑判定,返回bool值
every()、some();

实例演示:

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

var arr_map = arr.map(function(e){
    return e*2;
});
console.log(arr_map);  // [ 2, 4, 6, 8, 10 ]


var arr_filter = arr.filter(function(e){
    return e>3;
});
console.log(arr_filter);  //[ 4, 5 ]

//some()指是否至少存在一个元素符合判定
var flag = arr.some(function(e){
    return e>4;
});
console.log(flag);  //true

//every()指是否所有元素符合判定
var flag2 = arr.every(function(e){
    return e>4;
});
console.log(flag2);  //false

reduce()

该方法相对复杂一些,它接收一个函数作为累加器(accumulator),数组中的每个值(从左到右)开始合并,最终为一个值。声明类似:

reduce(callback(previousValue, currentValue, index, array),[initialValue]);

callback为传入函数,initialValue为第一次调用callback的第一个参数。具体含义如下:

  • previousValue :上次调用的返回值,或是initialValue初始值。
  • currentValue : 当前正被处理的元素
  • index :当前被处理元素索引
  • array :数组本身

    initialValue是非必填的,当不传时,使用数组的第一个元素作为初始值。

    示例:

    
    var arr = [1,2,3];
    
    var total = arr.reduce(function(previousValue, currentValue) {
    return previousValue + currentValue;
    
    },0);
    console.log(total);  //6
    

    来分析一下此函数执行,数组有3个元素,即传入的方法执行了3次。

    1. 第一次执行,currentValue 为1,previousValue为传入的初始值,即为0,返回1;
    2. previousValue为上次reduce()返回值1,currentValue为2,相加返回3;
    3. previousValue为3,currentValue为3,返回6。循环完成,返回6。

    上面方法其实就是求和操作。我们可以利用此函数进行许多操作。

    
    //求积   
    arr = [2,3,4];
    var product = arr.reduce(function(a,b){
    return a*b;
    
    },1);
    console.log(product); //24
    
    //求最小值
    //使用数组第一个元素作为初始值。
    arr = [2,4,10,6,9,3];
    var min= arr.reduce(function(a,b){
    return a>b?b:a;
    
    });
    console.log(min);  //2
    
    

    更多关于reduce()请参考
    MDN Array.prototype.reduce()

    全文完

你可能感兴趣的:(javascript)