数组是一种数据结构,内含一组有序元素.在js中,数组也是对象
参考
Object.prototype.toString方法的原理 紫云飞
How can I shuffle an array? stackoverflow
获取两个数间的随机数 stackoverflow
速查表
实例化(创建)数组
有两种方式创建数组
1 通过Array构造函数创建数组
new Array()
new Array(length | element1, element2...)
//不传入参数,返回空数组
var arr = new Array();
console.log(arr) //[]
//传入单个整数,返回该整数长度的空数组
var arr = new Array(3)
console.log(arr); //[empty × 3]
//传入单个非数字/多个对象,返回包含这些对象的数组
var arr = new Arry('3');
console.log(arr); //["3"]
注意 传入单个非整数数字会报错
var arr = new Array(3.1)
console.log(arr); //RangeError: Invalid array length
2 通过声明数组自面量的方式创建数组对象
[] // 创建一个空数组
[element1, element2,...] //创建一个数组,内含元素 element1 element2 ...
var array = [1, 2, 3]
console.log(array) // [1, 2, 3]
字面量(literal)是一种值的表示方法.看到该值,就能立刻明白该值是什么对象
1 true null {num:1}都是一种字面量
例如 数字17有很多种表示方法
var num = 17 // 十进制
var num = 0b10001 // 2进制
var num = 0x11 // 16进制
访问数组元素
可用一对中括号获取/设置数组元素
array[index]
index 数组元素的索引(),从0开始计数
// 获取数组的第一个元素
var arr = [1, 2, 3]
arr[0] // 1
也可用中括号修改指定的数组元素
// 更改数组的第一个元素
arr[0] = 'a'
console.log(arr) // ["a", 2, 3]
slice
获取一段数组元素,返回该段元素组成的新数组
array.slice() //如果参数为空,则返回包含所有元素的新数组
array.slice(startIndex)
array.slice(startIndex, endIndex)
var arr = [1, 2, 3];
arr.slice(0) // [1, 2, 3]
arr.slice(1) // [2, 3]
指针也可以从后向前计数,从-1开始
//获取倒数第一个元素
arr.slice(-1) // [3]
注意 所获元素不包含endIndex
//不包含最后一个元素
arr.slice(0,2) // [1, 2]
arr.slice(0,-1) //[1, 2]
数组长度
可用length属性获得/更改数组长度
array.length //返回数组长度
array.length = num //设置数组长度
var arr = [1, 2, 3];
arr.length // 3
arr.length = 10
console.log(arr) // [1, 2, 3, empty × 7]
//更改数组长度为1,相当于除第一个外的数组元素都被删除了
arr.length = 1
console.log(arr) //[1]
判断
判断对象是否是数组
Object.prototype.toString.call(object) === '[object Array]'
把toSring方法中的this指向需判断的对象,以此来获取内部Class属性值(只有这一个方法能取到)
Object.prototype.toString() //"[object Object]"
Object.prototype.toString.call([]) === '[object Array]'; //true
Object.prototype.toString.call({}) === '[object Array]'; //false
apply也一样
Object.prototype.toString.apply([]) // "[object Array]"
判断元素是否在数组
array.indexOf() // 返回该元素的下标,未找到返回 -1
['a'].indexOf('a') // 0
['a'].indexOf('b') // -1
'a'.indexOf('a') // 0
'aba'.indexOf('a',1) // 0 第二个参数定义起始搜索位置
添加元素
push
可通过push方法向数组尾部添加多个元素
array.push(element1, element2,...)
var arr = [];
arr.push(1);
console.log(arr) // [1]
可同时添加多个元素,元素间用逗号隔开
arr.push(2,3);
console.log(arr) // [1, 2, 3]
unshift
可通过push方法向数组头部插入元素
array.unshift(element1, element2,...)
var arr = [1];
arr.unshift(2);
console.log(arr); // [2, 1]
arr.unshift('a','b');
console.log(arr); // ["a", "b", 2, 1]
push | unshift方法会返回数组长度值
var len = arr.unshift();
console.log(len); // 5
concat
可用concat方法连接多个数组
array.concat()
array.concat(array1,array2,...)
var arr = [1]
var arr2 = arr.concat([2],[3])
console.log(arr2) // [1, 2, 3]
concat方法返回新的数组,不会修改原来的数组对象,因此可用于数组浅复制
var arr = [1];
var arrCopy = arr.concat();
arrCopy.push(2)
//可见原数组arr未发生改变
console.log(arr); // [1]
console.log(arrCopy); // [1, 2]
splice
插入/删除元素.返回一个数组,内含被删除的元素
array.splice(index)
array.splice(index,deleteCount)
array.splice(index,deleteCount,item1,item2,...)
index 插入元素位置,原来在该位置上的元素会自动向后挪
deleteCount 删除元素数个数,小于等于0时不删除元素
itemX 插入元素,可选
var arr = [1 ,2, 3];
arr.splice(0, 0,'a');
console.log(arr); // ["a", 1, 2, 3]
arr.splice(0, 1); // ["a"]
console.log(arr); // [1, 2, 3]
arr.splice(-1, 0, 'a', 'b');
console.log(arr); // [1, 2, "a", "b", 3]
删除元素
pop
array.pop()
删除数组末尾元素
var arr = ['a', 'b'];
arr.pop(); // "b"
arr; // ["a"]
shift
array.shift()
删除数组内第一个元素
var arr = ['a', 'b'];
arr.shift(); // "a"
arr // ["b"]
数组的拷贝(复制)
因为数组对象引用时传递的是内存地址,因此不能像复制字符串一样把数组赋值给其他变量
var arr = [1];
var arrc = arr;
arrc.push(2);
// 修改arrc,arr 也发生改变.因为这两个变量指向的是同一个数组对象.
console.log(arr); // [1, 2]
浅拷贝
浅拷贝只能复制字符串元素,不能复制数组/对象元素
array.slice()
array.concat()
var arr = [1];
var arrc = arr.slice();
console.log(arrc);
var arrc = arr.concat();
console.log(arrc); //[1]
数组里的数组/对象元素还是指向原来的元素
var arr= [1, [2], {num:3}]
var arrc= arr.slice();
// 修改新数组中的元素
arrc[0] = 'a'
arrc[1][0] = 'b'
arrc[2].num = 'c'
// 原数组中的数组和对象也被修改了
console.log(arr) // [1, ["b"], {num:"c"}]
arr.push('!');
console.log(arr); // ["a", "b", "c", "!"]
console.log(compareArr); // ["a", "b", "c", "!"]
console.log(arrCopy); // ["a", "b", "c"]
深拷贝
1 JSON.parse(JSON.stringify(array))
用于多维数组拷贝
var arr = [1, [2]]
var arrc = JSON.parse(JSON.stringify(arr));
arrc[1][0] = 'a';
//原数组没有被改变
console.log(arr[1]); // [2]
console.log(arr[3]); // ["!"]
console.log(compareArr[3]); // ["!"]
console.log(arrDeepCopy[3]); // ["d"]
缺点 不能拷贝函数和Data对象
var arr = [1,2,v => console.log(v)] // [1, 2, function]
JSON.parse(JSON.stringify(arr)); // [1, 2, null]
2 递归深拷贝
function deepCopy(arr) {
function _isArr(obj) {
// 检测是否是数组 , 返回布尔值
return Object.prototype.toString.call(obj) === '[object Array]';
}
var item;
var arrc = [];
for (var i = 0; i < arr.length; i++) {
if (_isArr(arr[i])) {
//数组
item = deepCopy(arr[i]);
} else if (arr[i].constructor === Object) {
//对象
item = {};
for (var key in arr[i]) {
var value = arr[i][key];
if (arr[i].hasOwnProperty(key) === true) {
item[key] = _isArr(value) ? deepCopy(value) : value;
}
}
} else{
//其他,例如字符串 Data等
item = arr[i];
}
arrc.push(item);
}
//for end
return arrc;
}
var arr = [1,[[2],], {num: [4, function(){console.log('hi')}]}]
var arrc = deepCopy(arr);
arrc[1][0] = 'a';
console.log(arr[1][0]); // [2]
arrc[2].num[0] = 'b';
console.log(arr[2].num[0]); // 4
arr[2].num[1]() //hi
注意 该函数未考虑互相调用的情况
var a = [];
var b = [];
a.push(b);
b.push(a);
deepCopy(a); // Uncaught RangeError: Maximum call stack size exceeded(…)
3 jQuery.extend
利用jQuery拷贝数组
jQuery.extend(true, {}, array) //深拷贝
jQuery.extend(false, {}, array) //浅拷贝
var arr = [1,[[2],], {num: [4, function(){console.log('hi')}]}]
var arrc = jQuery.extend(true, {}, arr)
数组转字符串
toString
array.toString()
var arr = [1 ,2 ,3];
arr.toString(); // "1,2,3"
join
array.join('sep')
sep 元素间的分隔符号,留空时使用逗号分隔
var arr = [1 ,2 ,3];
arr.join(); // "1,2,3"
arr.join(' '); // "1 2 3"
字符串转数组
string.split(sep)
string.split(regExp)
string.split(sep, Maxlength)
var str = "1,2,3"
str.split() // ["1,2,3"]
splite接受正则表达式作为分割依据
var str = "1,,2,,,,3"
str.split(/\,+/) // ["1", "2", "3"]
str.split(' ', 2) // ["1", "2"]
Maxlength 规定返回数组的最大长度
var str = "1,2,3"
//规定返回数组最大长度为2
str.split(',',2) // ["1", "2"]
数组的遍历
for
循环语句使用for关键字开头,后接括号.括号内包含三条语句(可选),使用分号(;)分隔
for(initialization; condition; final-expression){statement}
initialization 在循环开始时执行
condition 在单次循环开始前运行.运算结果为true将继续执行,反之结束运行(被省略则一直为true)
final-expression 单次循环结束后运行
var arr = ['a', 'b', 'c'];
for (var i = 0; i < arr.length; i++){
console.log(i); // 0 1 2
console.log(arr[i]); // a b c
}
这三条语句均可以被省略
var i = 0;
for(;;){
console.log(i++); // 0 1 2 3 ...
}
for in
for (var i in array){...}
var arr = ['a', 'b', 'c'];
for(var i in arr){
console.log(i); // 0 1 2
console.log(arr[i]); // a b c
}
for in循环中的i看起来像个数字,其实是数组对象的属性名
for(var i in ['a']){
console.log(i);
console.log(Object.prototype.toString.call(i) === '[object Number]'); // false
console.log(Object.prototype.toString.call(i) === '[object String]'); // true
}
因此,应尽量避免使用for in 遍历数组
var arr = ['a', 'b', 'c'];
//假设某个js库更改了array对象
Array.prototype.name = 'anna';
for(var i in arr){
//属性name也被遍历出来了
console.log(i); // 0 1 2 name
console.log(arr[i]); // a b c anna
}
//而普通的for循环就没有这种问题
for (var i = 0; i < arr.length; i++){
console.log(i); // 0 1 2
console.log(arr[i]); // a b c
}
for of
es6的新增方法
for (let i of arr){...}
var arr = ['a', 'b', 'c'];
for(let i of arr){
console.log(i); // a b c
}
数组排序
sort
利用sort方法对数组对象排序
arr.sort()
arr.sort(function)
var arr = [2, 1, 3];
arr.sort(); // [1, 2, 3]
可传入一个函数作为排序依据,根据返回值决定是否交换元素位置(返回值是否大于零)
var arr = [2, 1, 3];
arr.sort((x, y) => {return y - x;}); // [3, 2, 1]
//多维数组排序
var arr = [[2, 10],[1, 100],[3, 100]]
arr.sort((x,y) => {
// 以数组的第一个元素作为排序依据
return x[0] - y[0];
});
console.log(arr) //[ [1, 100], [2, 10], [3, 100]]
翻转数组
可用reverse方法翻转数组
array.reverse()
var arr = [1, 2, 3];
arr.reverse(); // [3, 2, 1]
注意 sort reverse方法返回的是原来的数组对象,不会返回新的数组
var arr = [2, 1, 3];
var arrt = arr.sort();
arrt[0] = 'a';
console.log(arr); // ["a", 2, 3]
随机排序
function shuffle(a) {
var j, x, i;
for (i = a.length - 1; i > 0; i--) {
j = Math.floor(Math.random() * (i + 1));
x = a[i];
a[i] = a[j];
a[j] = x;
}
}
suffle([1, 2, 3, 4, 5]);
How can I shuffle an array? stackoverflow
Math.random()
返回一个[0,1)之间的浮点数(小数)
Math.random() // 0.9480720531476523
// 取[0,100)间的数
Math.random() * 100 // 98.3447739091475
取[min,max)间的整数
Math.floor(Math.random() * (max - min + 1)) + min
// 取[10,100)间的整数
Math.floor(Math.random() * (100 - 10 + 1)) + 10
// 取[-10, 100]间的整数
Math.floor(Math.random() * (100 + 10 + 1)) - 10