JS数组
什么是数组
- 数组(Array)是有序数据集合
- 数组中的每个成员被称为元素(Element),每个元素的名称(键)被称为数组下标(index)
- 数组内不同元素的值可以为不同类型
- 数组的长度是弹性的、可读写的
- 在Javascript脚本中数组主要用于临时寄存同类数据,进行高速批量运算。
var arr = [123,"abc",null,undefined,{name:"xioawang"},true,[1,2,3],function () {
alert(1);
}];
console.log(arr);
// arr[arr.length - 1]();
arr.length = 100;
console.log(arr);
定义数组和读写数组
构造数组
- 使用new运算符调用Array()类型函数时,可以构造一个新数组
- 直接调用Array函数,不传递参数,可以创建一个空数组
- 传递多个值,可以创建一个实数组
- 传递一个数值参数,可以定义数组的长度,即包含元素的个数,参数值等于数组的length属性值,每个元素的值默认值为 undefined
- 使用中括号可以读写数组,中括号左侧是数组名称,中括号内为数组下标
// 1.构造数组:
var arr1 = new Array();//如果不传值,则构造一个空数组
console.log(arr1);
var arr2 = new Array("a","b",23,45);
console.log(arr2);
var arr3 = new Array(4);
console.log(arr3);//如果传递一个参数,是定义数组的长度
var arr4 = new Array("a");
console.log(arr4);
console.log(arr2[2]);//读取数组的值
数组直接量
数组直接量的语法格式:在中括号中包含多个值列表,值之间用号分隔(推荐使用数组直接量定文d 数组,因为数组直接量是定义数组最简便、最高效的方法)
var arr5 = [1,2,3,4,5];//直接量定义数组
console.log(arr5);
console.log(arr5[3]);//读取数组
多维数组
- Javascript不支持多维数组,设置元素的值等于数组,可以模拟二维数组结构,如果三维组中每个元素的值也为数组,则可以模拟三维数组,以此类推,通过数组套的形式可以定义多推数组
- 读写多维数组方法与普通方法相同,都是使用中括号进行访问
var arr6 = [1,2,3,[4,5,6],7];//定义一个二维数组
console.log(arr6);
console.log(arr6[3][1]);//二维数组的获取值
var arr7 = [1,2,3,4,5,[5,6,7,[8,9],11],10];//定义一个三维数组
console.log(arr7);
console.log(arr7[5][3][1]);//三维数组的获取
//使用for 把1-100的整数以二维的形式储存在数组中
var arr8 = [];
// 遍历10次,每次生成一个10个值的数组
for (var i = 0; i < 10; i++) {
// 创建一个新数组,每次遍历的时候,插入10个值,然后把这个数组,插入到arr8中
var arr9 = [];
//遍历10次,每次向arr9中插入1个值
for (var j = 0; j < 10; j++) {
arr9[j] = i * 10 + j + 1;
}
arr8[i] = arr9;
}
console.log(arr8);
空位数组
- 空位数组就是数组中包含空元素。所谓空元素,就是在语法上数组中两个逗号之间没有任何值。出现空位数组的情况如下
- 直接量定义
- 构造函数定义
- delete删除
- 空元素可以读写, length属性不排斥空位,如果使用for语句和 length属性遍历数组,空元素都可以 被读取,空元素返回值为undefined
var arr10 = [1,2,,4];//空位数组,找不到,所以空位的值返回undefined
var arr11 = [1,2,undefined,4];//有值,值为undefined
console.log(arr10);
console.log(arr11);
关联数组
- 如果数组的下标值超出范围,如负数、浮点数、布尔值、对象或其他值,js会自动把它转换为一个字符串,并定义为关联数组。
- 关联数组就是与数组关联的对象,简单地说就是数组对象,字符串下标就是数组对象的属性
var arr12 = [1,2]; arr12[3.1] = "haha";//相当于给数组扩展了一些属性和方法 arr12[true] = "buer"; console.log(arr12); console.log(arr12[3.1]);
伪类数组
- 伪类数组,也称为类数组,即类似数组结构的对象。
- 简单地说,就是对象的属性名为非负整数,且从0开始,有序递增,同时包含length属性,还应确保其值与有序下标属性个数保持动态一致,以方便对伪类数组进行选代操作。
- 由于数字数非法标识符,所以需要用中括号来读写属性
var obj1 = { 0:"a", 1:"2", 2:"c", 3:"d", length:4 } console.log(obj1[1]);
斐波那契数列
//打印出斐波那契数列的前100个值 在数组中
// 1,2,3,5,8,13 初始值1和2 其他的值是前两个值的和
// arr[6] = arr[4]+arr[5]
var arr = [1,2];
for (var i = 2; i < 100; i++) {
arr[i] = arr[i-2] + arr[i-1];
}
console.log(arr);
数组的长度
- 每个数组都有一个length属性,该属性返回数组的最大长度。
- length属性可读可写,是一个动态属性。
- length属性值也会随数组元素的变化而自动更新。同时如果重置了length属性值,也将影响数组的元素。
var arr1 = [];
arr1.length = 100;
console.log(arr1);//empty*100
console.log(arr1[10]);//undefined
var arr2 = [1,2,3];
arr2.length = 5;
console.log(arr2);
var arr3 = [1,2,3,4,5,6,7];
arr3.length = 2;
console.log(arr3);//[1,2]
操作数组
栈操作
- 使用push()和pop()方法,可以在数组的尾部执行操作。
- 其中push方法,能够把一个或多个参数附加到数组的尾部,并返回附加元素以后,数组的长度
- pop方法是能够删除数组中的最后一个元素,并返回删除的值
- 补充:栈是先进后出,后进先出的原则。类似的情况是,叠放物品,或者子弹上膛
var arr = [];//空栈
console.log(arr.push(1));//入栈 返回新长度
console.log(arr.push(2,3));//入栈 一次可以插入多个值 返回新长度
console.log(arr);
console.log(arr.pop());//出栈 返回删除的值
console.log(arr.pop());//出栈 返回删除的值
console.log(arr);
- 栈操作练习
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>栈操作练习 -进制转换</title>
</head>
<body>
<script>
function to2b(num) {
var arr = [];//一个新栈,把每次生成的余数压到栈里
var r = null;//用来保存每次生成的余数
var s = "";//最后返回的二进制字符串
while(num > 0){
r = num % 2;//求出每次的余数
arr.push(r);//把余数入栈
num = parseInt(num / 2);//求出num计算后的值 并向下取整
}
while(arr.length > 0){
s += arr.pop();//pop是把最后一个值删了 并返回出来 和s拼接 放在了s的首位
}
return s;
}
console.log(to2b(100));
console.log(to2b(1000));
console.log(to2b(3));
// console.log((100).toString(2));//1100100
</script>
</body>
</html>
- 栈数据结构方法封装
var arr = [3,5,2,3,6,1,6];
// push:添加一个新元素到栈顶
function push(arr) {
// arguments
for (var i = 1; i < arguments.length; i++) {
arr.push(arguments[i]);
}
}
push(arr,1,2,3)
// pop方法 移出栈顶的元素 并且得到移出的值
function pop(arr) {
return arr.pop();
}
// peek:返回栈顶元素 不对栈做修改
function peek(arr) {
return arr[arr.length - 1]
}
// console.log(peek(arr));
// isEmpty 判断栈中是否为空 如果为空则返回true 否则返回false
function isEmpty(arr) {
return arr.length == 0
}
// clear:清空整个栈
function clear(arr) {
arr.length = 0;
}
// size:返回栈里的个数
function size(arr) {
return arr.length;
}
- 栈结构练习-可定制的进制转换
//封装一个栈操作的一个类 想要使用 直接new 实例化
//实例化得到的对象 就会拥有这些方法
function Stack() {
this.arr = [];
this.push = function (item) {
this.arr.push(item);
};
this.pop = function () {
return this.arr.pop();
};
this.peek = function () {
return this.arr[this.arr.length - 1];
};
this.isEmpty =function () {
return this.arr.length == 0;
};
this.clear = function () {
this.arr = [];
};
this.size = function () {
return this.arr.length;
};
}
// 16进制以下所有进制转换算法
function divideBy2(num,para) {
//把Stack实例化以后 所有的remStack就会拥有Stack这个类的属性和方法
var remStack = new Stack();
var rem;
var binarySting = "";
var str = "0123456789abcdef";
//循环插入栈
while(num>0){
rem = parseInt(num % para);
remStack.push(rem);
num = parseInt(num / para);
}
// 当全部插入完成以后,对栈进行一个移出的操作
while(!remStack.isEmpty()){
binarySting += str[remStack.pop()];
}
return binarySting;
}
console.log(divideBy2(2821355,12));
console.log(divideBy2(4,16));
队列操作
- 使用unshift()和 shift()方法可以在数组头部执行操作
- 其中unshift()能够把一个或多个参数值附加到数组的头部,第1个参数为数组新的元素0,第2个参数为新的元素1,以此类推,最后返回添加元素后的数组长度
- shift方法能够删除数组第1s个元素,并返回该元素,然后将余下所有元素前移1位,以填补数组头部的空缺。如果数组为空, shift将不进行任何操作,返回 undefined
- 使用 unshift分批插入元素与一次性插入元素结果是不同的
- 将pop()与 unshift()方法结合,或者将 push()与 shift()方法结合使用,可以模拟队列
// 利用队列模式把数组元素的所有值放大10倍
var a = [1,2,3,4,5];
for(var i in a){
var t = a.pop();
a.unshift(t*10);
}
console.log(a);
- 补充:队列也是一种运算受限的线性表,不过与栈操作不同,队列只允许在一端进行插入操作,在另一端进行删除操作。
- 队列通循先进先出、后进后出的原则,类似的行为在生活中比较常见,如排队购物、任务排序等。在 Javascript动画设计中,也会用到队列操作来设计回调函数。
- 击鼓传花练习
// 猴子找大王游戏
// 有一群猴子排成一圈,按1、2、3、…、n依次编号,然后从第1只开始数,数到第m只,则把它踢出圈,然后从它后面再开始数,当再次数到第m只,继续把它踢出去,以此类推,直到只剩下一只猴子为止,那只猴子就叫作大王。要求编程模拟此过程,输入m和n,输出最后那个大王的编号
// n表示猴子个数,m表示踢出位置
function f(n,m){
//将猴子编号并放入数组
var arr = [];
for(var i = 1;i < n+1;i++){
arr.push(i);
}
//当数组内只剩下一只猴子的时候跳出循环
while(arr.lenght>1){
//定义排队轮转次数
for(var i = 0;i<m-1;i++){
//队列操作完成轮转
arr.push(arr.shisft());
}
arr.shift();//提出第m只猴子
}
return arr;
}
- 队列结构的封装
/* enqueue:向队列的尾部添加新的项
dequeue:移除队列的第一个项,并返回被移除的元素
front:返回队列的第一个元素,队列不做任何的改动
isEmpty:如果队列中不包含任何元素,返回true,则返回true,否则返回false
size:返回队列包含的元素个数
*/
function Queue() {
this.arr = [];
this.enqueue = function (item) {
this.arr.push(item)
}
this.dequeue = function () {
this.arr.shift();
}
this.front = function () {
return this.arr[0];
}
this.isEmpty = function () {
// return this.arr.length == 0;
return !this.arr.length;
}
this.size = function () {
return this.arr.length;
}
}
var queue1 = new Queue();
删除元素
- 使用pop方法可以删除尾部的元素,使用shift方法可以删除头部的元素
- 使用delete运算符能删除指定下标位置的数组元素,删除后的元素为空位元素,删除数组length保持不变
- 使用length属性可以删除尾部一个或多个元素,甚至可以清空整个数组
- 使用splice方法可以删除指定下标位置后一个或多个数组元素(个数)
// 使用delete删除指定下标的元素
var arr1 = [1,2,3,4,5];
delete arr1[2];//删除指定下标的值,当前的值为空,所以数组变成了空位数组 长度不变
console.log(arr1);
// 使用length属性也可以删除数组
var arr2 = [1,2,3,4];
arr2.length = 1;
console.log(arr2);
var arr3 = [1,2,3,4,5,5,6,7,8,8];
console.log(arr3.splice(3));//一个参数代表删到末尾
console.log(arr3);//[1,2,3]
var arr4 = [1,2,3,4,5,5,6,7,8,8];
console.log(arr4.splice(3,3));//两个个参数代表删几个 [4,5,5]
console.log(arr4);//[1,2,3,6,7,8,8]
添加元素
- 使用 push方法可以在尾部添加一个或多个元素,使用 unshift方法可以在头部附加一个或多个元素
- 通过中括号和下标值,可以为数组指定下标位置添加新元法来添加元素
- concat方法能够把传递的所有参数按顺序添加到数组的尾部
- concat方法可以跟随多个参数,并把它们作为元素按顺序连接到数组的尾部
- 如果参数是数组,则concat方法会把它打散,分别作为单独的元素连接到数组的尾部
- 不过concat方法仅能够打散一维数组,它不会打散二维的数组。
- concat方法将创建并返回一个新数组,而不是在原来数组基础上添加新元素。所以,如果要在原数组着础上添加元素,建议使用 push方法和unshift方法来实现。但是 push方法和 unshift方法不能够打散参数数组,而是把它作为单独的参数执行添加操作
- 使用 splice方法在指定下标位置后添加一个或多个元素
// 可以使用中括号和下标值 来添加元素,或者是修改元素
var arr1 = [1,2,3,4,5];
arr1[5] = 6;
arr1[10] = 10;//如果给后边元素设置值,中间的空白就变成了空位元素
arr1[1] = "a";//这种方法只能给空位元素设置,或者是其他的没有的位置设置,否则就修改了元素
console.log(arr1);
// concat方法
var arr2 = ["a","b","c"];
console.log(arr2.concat(1, 2, 3));;
console.log(arr2);//原数组不改变
var arr2 = ["a","b","c"];
arr2.push([1,2,3]);//push插入会把数组直接当成1个值插入
console.log(arr2);
var arr2 = ["a","b","c"];
console.log(arr2.concat([1, 2, 3,[4,4,4]]));
// splice方法可以在指定位置的下标添加元素
var arr3 = ["a","b","c","d","e","f"];
arr3.splice(2,0,"g","h");//无论是否删除,都会把第三个参数以后的所有参数 按顺序放在第一个参数下标标记的位置
console.log(arr3);
使用 splice()方法
- splice()方法的参数都是可选的。如果不给它传递参数,则该方法不执行任何操作
- 如果给它传递一个数,则该方法仅执行删除操作,参数值指定删除元素的起始下标(包括该下标元素),splice方法将删除后面所有
- 如果指定两个参数,则第2个参数值表示要别删除元素的个数。
- 如果指定三个或多个参数,则第3个以及后面所有参数都被视为插入的元素
- 如果不执行删除操作,第2个参数值应该设置为0,但是不能够空缺,否则该方法无效
- splice方法执行的返回值是被别除的子数组
- 当第1个参数值大于length属性值时,被视为在数组尾部执行操作,因此删除无效,但是可以在尾部插入多个指定元素
- 参数取负值问题。如果第1个参数为负值,则按绝对值从数组右侧开始向左侧定位。如果第2个参数为负值,则被视为0。
var arr1 = [1,2,3,4,5,6,7];
console.log(arr1.splice(4));//[5,6,7]
console.log(arr1);//[1,2,3,4]
var arr2 = [1,2,3,4,5,6,7];
console.log(arr2.splice(1,3));//[2,3,4]
console.log(arr1);//[1,5,6,7]
var arr3 = [1,2,3,4,5,6,7];
console.log(arr3.splice(2,1,"a","b","c"));//[3]
console.log(arr3);//[1,2,a,b,c,4,5,6,7]
var arr4 = [1,2,3,4,5,6,7];
console.log(arr4.splice(10,2,"a","b","c"));//[]
console.log(arr4);//[1,2,3,4,5,6,7,a,b,c]
var arr5 = [1,2,3,4,5,6,7];
console.log(arr5.splice(-5,2,"a","b","c"));//[3,4]
console.log(arr5);//[1,2,a,b,c,5,6,7]
var arr5 = [1,2,3,4,5,6,7];
console.log(arr5.splice(-5,-2,"a","b","c"));//[]
console.log(arr5
