目录

1、定义数组

2、存取数组元素

3、查看数组元素

4、删除数组元素

5、数组长度 length

6、数组元素排序

7、对象和数组

8、定义多维数组


数组(Array)是一种有序数据集合,数组中每个值被称为数组的一个元素(Element),每个元素的编码被称为数组下标(Index)。JavaScript 是弱类型语言,数组结构表现和语法约定都比较松散,每个元素的值可以为任意类型,同一数组的不同元素可以保存不同类型数据,数组长度不是固定的,可以任意地拉伸和收缩。JavaScript 不支持二维或多维数组,通过元素包含数组的方式,可以间接创建复杂的多维数组。

注:严格意义上说,JavaScript 中的数组对象并不能称为真正意义上的数组。在 C 语言 、Java 等严格数据类型的语言中,数组中各个元素的数据类型相同,数组的存储位置在内存中是连续的,可以通过数字下标获取数组元素。而 JavaScript 中的数组是这样的,数组中各元素的数据类型可以不同,内存不一定是连续的(对象是随机存储的),不能通过数字下标,而是通过字符串下标来访问数组元素,这意味着数组可以有任何 key ,比如:let arr = [1,2,3];arr['xxx'] = 1。

总之,JavaScript  中的数组本质上是对象,是通过对象的 key 和 value 键值对来模拟的数组。

1、定义数组

(1)使用构造函数 Array()

//当调用Array构造函数时,,没有传递参数,可以创建一个空数组
var a = new Array();    //空数组

//当调用Array构造函数时,仅给Array构造函数传递一个数值参数,该数值定义了数组的长度,即定义数组中包含元素的个数。
var a = new Array(5);    //指定长度的数组,在这种形式中,参数值等于数组的 lengh 属性值,每个元素的值预定义为 undefined。

//当调用Array构造函数时,明确指定数组的元素,可以创建一个实数组
var a = new Array(1,true,"string",[1,2],{x:1,y:2});    //实数组

(2)使用数组直接量 [ ]

var a = [];    //空的数组直接量
var a = [1,true,"string",[1,2],{x:1,y:2}];    //包含具体元素的数组直接量

使用直接量定义数组,能够提高数组初始化运行效率。因此,在没有特殊要求的情况下建议使用直接量定义数组。

(3)其他的花里胡哨法创建数组:

let arr = '1,2,3'.split(',');
console.log(arr);     //["1","2","3"];

let arr = '123'.split('');
console.log(arr);     //["1","2","3"];

Array.from('123');    //ES6的新转增语法
console.log(arr);     //["1","2","3"];

Array.from({0:'a',1:'b',2:'c',3:'d',length:4});    //这种方式构造的数组是伪数组,它的原型链中没有数组的原型
console.log(arr);    //["a","b","c","d"];          //伪数组虽然有数组的性质,但是没有数组原型,及数组原型方法

let divList = document.querySelectorAll('div');    //伪数组,divList.__proto__.__proto__ === Object.prototype
let divArray = Array.from(divList);    //可以将伪数组转化为真数组,divArray.__proto__ === Array.prototype

let arr1 = [1,2,3,4];
let arr2 = [5,6,7,8];
console.log(arr1.concat(arr2));    //[1,2,3,4,5,6,7,8],但是arr1和arr2本身并没改变

let arr = [1,2,3,4,5,6,7,8];
console.log(arr.slice(3));    //[4,5,6,7,8],但是arr本身并内有改变
console.log(arr.slice(0));    //[1,2,3,4,5,6,7,8],可以用slice方法复制一个数组

2、存取数组元素

(1)取数组元素值主要通过中括号运算符([ ])来实现。中括号运算符左侧是数组标识符,中括号内指定数组元素的下标

var a = [];        //声明一个空数组直接量,并把它引用给变量 a
a[0] = 1;          //为数组第一个元素赋值为 1
a[2] = 2;          //为数组第三个元素赋值为 2
alert(a[0]);       //读取数组第一个元素的值,返回值为 1
alert(a[1]);       //读取数组第二个元素的值,返回值为 undefined
alert(a[2]);       //读取数组第三个元素的值,返回值为 2

在存取数组元素操作中,应注意以下几个问题。

1> 在JavaScript中,数组长度是弹性的,可以在操作中随时扩展数组的长度。例如,在上面示例中虽然仅给下标为 0 和 2 位置的元素赋值,但是 JavaScript 会自动为下标为 1 的元素预定义为 undefined。

2> JavaScript 数组下标是以 0 开始的。下标可以是值为非负整数的表达式。

(2)可以通过 push() 方法在数组尾部添加元素:

let arr = [0,1,2,3,4];
arr.push(5);        //向数组尾部添加元素5
console.log(arr);   //[0,1,2,3,4,5]

arr.push('x','y');  //向数组尾部添加元素'x','y'
console.log(arr);   //[0,1,2,3,4,5,'x','y']

(3)可以通过 unshift() 方法向数组首部添加元素:

let arr = [0,1,2,3,4];
arr.unshift(5);     //向数组头部添加元素 5
console.log(arr);   //[5,0,1,2,3,4]

arr.unshift('x','y');   //向数组头部添加元素 'x','y'
console.log(arr);   //['x','y',5,0,1,2,3,4]

(4)可以通过 splice()

let arr = [0,1,2,3,4];

arr.splice(2,1,'x')     //在下标为2的位置删除1个元素,并插入 'x'
console.log(arr);       //[0,1,'x',3,4]

arr.splice(2,0,'x','y')  //在下标为2的位置删除0个元素,并插入 'x','y'
console.log(arr);       //[0,1,'x','y','x',3,4]

3、查看数组元素

(1)可以通过 Object.keys() 方法查看数组的属性名:

let arr = [0,1,2,3,4];
arr.x = 'x';    //通过点运算符给数组添加元素,但是数组的 length 属性并未改变,仍然是 5
console.log(Object.keys(arr));      //["0","1","2","3","4","×"]
console.log(Object.values(arr));    //[0,1,2,3,4,'x']

for(let key in arr){    //for-in 语句会自动索引数组中的所有key
    console.log(`${key}:${arr[key]}`)    //0:0  1:1 2:2  3:3  4:4  x:x
}

(2)通过 indexOf()、find()、findIndex()

let arr = [0,1,2,3,4];

console.log(arr.indexOf(3));    //3    存在返回索引,否则返回-1

arr.find( item => item%2 === 0 );         //找第一个偶数,会返回 2
arr.findIndex( item => item%2 === 0 );    //找第一个偶数的索引,会返回 2

(3)结合数组的 length

let arr = [0,1,2,3,4];
arr.x = 'x';    //通过点运算符给数组添加元素,但是数组的 length 属性并未改变,仍然是 5

for(let i=0;i<arr.length;i++){
    console.log(`${key}:${arr[key]}`)    //0:0  1:1 2:2  3:3  4:4
}

(4)还可以通过 forEach() 方法遍历查看数组元素:(forEach() 方法:对数组元素进行指定的回调操作)

array.forEach(callbackfun[value,index,array])
 
//1、array:一个数组对象。
//2、callbackfun:必需参数,最多可以接收 3 个参数的函数。
//    对于数组中的每个元素,forEach 都会调用 callbackfun 函数一次。
//3、thisArg:可选参数,callbackfun 函数中的 this 关键字可引用的对象。
//    用户可以使用最多3个参数来声明回调函数。回调函数的参数说明如下:
//    value:数组元素的值、index:数组元素的数字索引、array:包含该元素的数组对象。

let arr = [0,1,2,3,4];
arr.forEach( function(item,index){    //forEach函数的参数接收一个回调函数
    console.log(`${index}:${item}`);  //回调函数中传递数组的item值和index下标
} )

注意:上述 3 和 4 两种遍历数组的方式的区别:(1)前者 for 是关键字,没有函数,所以它是块级作用域,后者是 forEach 是函数,它是函数作用域。(2)前者支持 break 和 continue,后者不支持,forEach 一旦执行,无法中断。

4、删除数组元素

(1)可以通过 delete 删除数组元素:(不推荐)

let arr = [0,1,2];
delete arr[0];       //删除数组的第一个元素
console.log(arr);    //[empty,1,2]
console.log(arr.length);    //3    这就很神奇了,通过delete删除数组元素,其数组的length并不会改变 —— 稀疏数组

(2)可以通过直接修改 length 删除数组元素:(不推荐)

let arr = [0,1,2,3,4,5];    //此时数组长度为6
arr.length = 3;        //将数组长度改为3
console.log(arr);      //[0,1,2]    大于数组长度的元素都被删除了

(3)可以通过 shift()

let arr = [0,1,2,3,4,5];
let temp = arr.shift();      //删除数组头部元素,此时arr被修改,并返回被删元素
console.log(temp);    //0    表示被删除的元素为0
console.log(arr);     //[1,2,3,4,5]

(4)可以通过 pop() 方法删除数组尾部元素:

let arr = [0,1,2,3,4,5];
let temp = arr.pop();      //删除数组尾部元素,此时arr被修改,并返回被删元素
console.log(temp);    //5    表示被删除的元素为0
console.log(arr);     //[0,1,2,3,4]

(5)可以通过 splice() 方法删除数组指定位置的元素:

arr.splice(index,num,...);        //从下标为index的地方开始删除,往后删除num个元素
//其中第 1 个参数为操作的起始下标位置,第 2 个参数指定要删除元素的个数,第 3 个元素及后面的所有不定参数都为将要插入的元素。

let arr = [0,1,2,3,4,5];
arr.splice(2,1);     //从下标为2的元素开始删,删除1个元素
console.log(arr);    //[0,1,3,4]

let arr = [0,1,2,3,4,5];
arr.splice(2,1,'x');    //从下标为2的元素开始删,删除1个元素,并在删除位置添加 'x'
console.log(arr);       //[0,1,'x',3,4]


let arr = [0,1,2,3,4,5];
arr.splice(2,1,'x');            //从下标为2的元素开始删,删除1个元素,并在删除位置添加 'x','y'
arr.splice(index,1,'x','y');    //[0,1,'x','y',3,4]

5、数组长度 length

在传统语言中,数组一旦被声明,其长度是固定的,但是 JavaScript 数组很灵活,数组元素的个数可以进行任意修改。不用考虑所定义的元素是否超出数组的长度,或者下标是否保持连续值。

var a = [];        //声明空数组
a[2] = 1;          //为下标为2的元素赋值
s[100] = 2;        //为下标为100的元素赋值
for(var i in a){   //遇历数组,仅能够读取两个元素,说明其他元素不存在
    alert(a[i]);
}

JavaScript 在初始化数组时,只有那些真正存储在数组中的元素才能够被分配到内存中去。因此,在上面示例中 JavaScript 解释器只给数组下标为 2 和 100 的元素分配内存,而并不给其他下标值的元素分配内存。但是用户可以存取其他下标元素:

alert(a[0]);    //返回undefined,说明没有这个元素
alert(a[1]);    //返回undefined,说明没有这个元素
a[0] = 3;       //为数组下标值等于0的元素赋值为3
a[1] = 4;       //为数组下标值等于1的元素赋值为4
alert(a[0]);    //返回3,说明该元素存在
alert(a[1]);    //返回4,说明该元素存在

这说明 JavaScript 数组中的元素值,以及元素个数都是动态的,且元素下标是否为连续值都不重要。

JavaScript 为 Array 对象预定义了一个 length 属性,该属性将被所有数组对象继承,不管是由 Array() 构造函数创建的数组,还是由数组直接量定义的数组。length 属性存储了数组包含的元素个数。length 属性值不是数组元素的实际个数,而是当前数组的最大元素个数。由于数组下标可以是非连续的,因此 length 属性的值总是等于数组最大下标值加上 1。

var a = [];    //声明空数组
a[2] = 1;
a[100] = 2;
alert(a.length);    //返回101

a[200] = 200;
alert(a.length);    //返回201    数组的 length 属性是一个动态值,当数组添加了新元素之后,它的值也会自动更新。

作为动态值,数组的 length 属性可以被更新,如果 length 属性被设置了一个比当前 length 值小的值,则数组将会被截断,新长度之外的元素值都会被丢失;如果 length 属性被设置了一个比当前 length 值大的值,那么新的未定义的元素就会被添加到数组末尾,以使得数组增长到新指定的长度,其默认值为 undefined。

var a = [1,2,3];    //声明数组直接量
a.length = 5;       //增长数组长度
alert(a[4]);        //返回undefined,说明该元素还没有被赋值
a.length = 2;       //缩短数组长度
alert(a[2]);        //返回undefined,说明该元素的值已经丢失

6、数组元素排序

(1)可以使用 reverse() 方法反转数组中的元素:

var a = [1,2,3,4,5];    //定义数组
a.reverse();    //颠倒数组顺序,reverse() 能够在原数组的基础上颠倒数组元素的排列顺序,该方法不需要参数。
alert(a);    //这回数组[5,4,3,2,1]
 
//快速反转一个字符串
let str = 'abcde';
str.split('').reverse().join(''); //先将str字符串split()成一个数组,数组的reverse()方法,再join()将数组元素练成字符串

(2)可以通过 sort()

let arr = [3,1,5,2,4];    //乱序数组
arr.sort();
console.log(arr);    //[1,2,3,4,5]

function compare(value1,value2){    //排序函数
    if(valuel < value2){
        return 1;
    }else if (value1 > value2){
        return -1;
    }else{
        return 0;
}
function compare(value1,value2){    //排序函数的改写
    return (value2 - value1)        //返回比较参数
}

arr.sort( (value1,value2) => value1-value2 );    //或者改成箭头函数

var arr = [3,1,2,4,5,7,6,8,0,9];    //定义数组
arr.sort(compare);    //根据数字大小由小到大进行排序
alert(arr);           //返回数组[0,1,2,3,4,5,6,7,8,9]

7、对象和数组

对象(Object)与数组(Array)是两种不同类型的引用型数据。从数据存储的方式上来看,它们非常相似。对象是一种包含已命名的值的集合类型,而数组则是一种包含己编码的值的集合类型。

var o = {        //对象                    var a = [        //数组
    x : 1,       //该值命名为 x                1,           //该值隐含编码为 0
    y : true     //该值名命为 y                true         //该值隐含编码为 1
}                                         ]

由于对象的数据存储形式很像数组,因此被称为关联数组,但是它不是真正意义上的数组。关联数组就是将值与特定字符串关联在起。真正的数组与字符串没有联系,但是它将值和数值(非负整数的下标)关联在一起。

alert(o["x"]);    //返回1,在对象 o 中,值 1 与字符串 x 关联在一起
alert(a[0]);      //返回1,在数组 a 中,值 1 与数值 0 关联在一起

使用 点运算符(.)可以存取对象属性,而数组使用 中括号([ ])来存取属性。针对上面对象属性的读取操作,下面两行代码的意思是相同的:

o.x;        //返回1,使用点运算符存取属性
o["x"];     //返回1,使用中括号运算符存取属性

使用点运算符存取属性时,属性名是标识符,而使用中括号运算符存取属性时,属性名是字符串。

typeof 运算符提示数组实际上为对象类型,其返回值为字符串"Object"。

var a = [1,2,3];        //数组直接量
alert(typeof a);        //返回数组类型为object,而不是Array
alert(a.constructor == Array);    //返回true,说明数组直接量的构造器是Array

8、定义多维数组

JavaScript 不支持多维数组,但是多维数组在实际开发中非常实用,用户可以通过数组嵌套的形式定义多维数组。

var a = [    //定义二维数组
    [1,2,3],
    [4,5,6],
    [7,8,9]
};

要存取二维数组的元素,只需要使用 两次中括号运算符 即可。对于多维数组,则方法依此类推即可。

alert(a[0][0]);    //返回1,读取第1个元素的值
alext(a[2][2]);    //返回9,读取第9个元素的值
 
//在存取多维数组时,左侧中括号内的下标值不能够超出数组实际下标,否则就会提示系统错误:
alert(a[3][2]);        //提示编译错误

因为 JavaScript 解释器是按着从左到右的顺序来存取的,如果第一个下标超出,则元素值为 undefined,显然表达式undefined[2] 是错误的。