前言:这是笔者学习之后自己的理解与整理。如果有错误或者疑问的地方,请大家指正,我会持续更新!
数组的增删
- 第一个数组元素的索引值为 0,第二个索引值为 1,始终递增。
- 数组可以在头部增加元素
arr.unshift()
。- 也可以在尾部增加元素
arr.push()
。 - 增加元素的共同点是都是在原数组上修改,可顺序添加多个元素,并且返回数组的新长度。
- 也可以在尾部增加元素
- 数组可以在头部删除元素
arr.shift()
。- 也可以在尾部删除元素
arr.pop()
。 - 删除元素的共同点是都是在原数组上修改,一次只删一个元素,并且返回这个被删掉的元素。
- 也可以在尾部删除元素
- 由于
arr.unshift()
有兼容性问题,我们可以用arr.splice(0,0,item1,...)
代替,来在首位添加元素。
arr.push(newElement1,newElement2...)
- 将新参数按顺序添加到原数组尾部。
- 它是直接在原数组上修改。
- 返回值是数组的新长度。
var arr = [123, 'apple'];
console.log(arr.push({
name: 'lucy',
age: 18
}, 'lily', 456)); //5
console.log(arr); //[123,'apple',{name:'lucy',age:18},'lily',456]
arr.pop()
- 删除并返回数组的最后一个元素。
- 它是直接在原数组上修改,所以数组长度-1。
- 如果原数组本身已经没有元素,那么会返回
undefined
。
var arr = [123, 'apple', {
name: 'lucy',
age: 18
}];
console.log(arr.pop()); //{name:'lucy',age:18}
console.log(arr); //[123,'apple']
console.log(arr.pop()); //apple
console.log(arr); //[123]
console.log(arr.pop()); //123
console.log(arr); //[]
console.log(arr.pop()); //undefined
arr.unshift(newElement1,newElement2...)
- 将新参数按顺序添加到原数组头部。
- 它是直接在原数组上修改。
- 标准浏览器中返回值是数组的新长度,IE6/IE7 中返回值是
undefined
,所以这个方法会产生兼容性问题,一般不用。 - 我们可以用
arr.splice(0,0,item1,...)
代替,来在首位添加元素;
var arr = [123, 'apple'];
console.log(arr.unshift({
name: 'lucy',
age: 18
}, 'lily', 456)); //5
console.log(arr); //[{name:'lucy',age:18},'lily',456,123,'apple']
arr.shift()
- 删除并返回数组的第一个元素。
- 它是直接在原数组上修改,所以数组长度-1。
- 如果原数组本身已经没有元素,那么会返回
undefine
。
var arr = [123, 'apple', {
name: 'lucy',
age: 18
}];
console.log(arr.shift()); //123
console.log(arr); //['apple',{name:'lucy',age:18}]
console.log(arr.shift()); //apple
console.log(arr); //[{name:'lucy',age:18}]
console.log(arr.shift()); //{name:'lucy',age:18}
console.log(arr); //[]
console.log(arr.shift()); //undefined
数组转换字符串
arr.join('分隔符')
- 把数组元素放入一个新的字符串中(原数组并没有被改变),元素通过分隔符分隔。原数组不变。
- 如果不写分隔符,则默认用逗号分隔。
var arr = [123, 'apple', {
name: 'lucy',
age: 18
}];
//默认不分割,直接在最外层转换字符串包括了里面的逗号
console.log(arr.join()); //123,apple,[object Object]
//有引号,但没有分割内容,以逗号分隔,然后拼接字符串
console.log(arr.join('')); //123apple[object Object]
//以空格为分隔符
console.log(arr.join(' ')); //123 apple [object Object]
//注意原arr本身并没有被改变
console.log(arr); //[123,'apple',{name:'lucy',age:18}]
arr.toString()
- 把数组转换为字符串,并返回结果。
- 元素之间用逗号分隔。
- 原数组本身并没有被改变。
var arr = [123, 'apple', {
name: 'lucy',
age: 18
}];
console.log(arr.toString()); //123 apple [object Object]
//注意原arr本身并没有被改变
console.log(arr); //[123,'apple',{name:'lucy',age:18}]
其他类型转换成数组
Array.of(newElement1,newElement2,...)
Array.of
用于将参数依次转化为新数组中的一项,然后返回这个新数组,而不管这个参数是数字还是其它。
Array.of(8.0, 5); // [8, 5]
Array(8.0, 5); // [8, 5]
//IE6-IE8兼容性写法
if (!Array.of){
Array.of = function(){
return Array.prototype.slice.call(arguments);
};
}
Array.from(arrayLike,processingFn,[thisArg])
Array.from
的设计初衷是快速便捷的基于其他对象创建新数组,准确来说就是从一个类似数组的可迭代对象创建一个新的数组实例。简单说就是,只要一个对象有迭代器,Array.from
就能把它变成一个数组(当然,是返回新的数组,不改变原对象)。Array.from
拥有3个形参,第一个为类似数组的对象,必选。第二个为加工函数,新生成的数组会经过该函数的加工再返回。第三个为this
作用域,表示加工函数执行时this
的值。后两个参数都是可选的。我们来看看用法。
// String
Array.from('abc'); // ["a", "b", "c"]
// Set
Array.from(new Set(['abc', 'def'])); // ["abc", "def"]
// Map
Array.from(new Map([[1, 'abc'], [2, 'def']])); // [[1, 'abc'], [2, 'def']]
// 天生的类数组对象arguments
function fn(){
return Array.from(arguments);
}
fn(1, 2, 3); // [1, 2, 3]
// 生成一个从0到指定数字的新数组
Array.from({length: 10}, (v, i) = i); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
数组的裁剪、拼接
arr.slice(start,end)
- 返回的是一个新的数组(选定的元素),从引脚
start
到end
(不包含)。 - 原数组并没有被改变。
start
可以设置负值,负值就是从数组末尾开始,-1是最后一个元素,-2是倒数第二个元素。end
是可选值,如果没有设置end
,就默认截取到数组末尾。- 数组的
arr.slice()
和string.slice()
很相似。
var arr = [123, 'apple', {
name: 'lucy',
age: 18
}];
console.log(arr.slice(0)); //[123,'apple',{name:'lucy',age:18}]
console.log(arr); //[123,'apple',{name:'lucy',age:18}]
console.log(arr.slice(1)); //['apple',{name:'lucy',age:18}]
console.log(arr); //[123,'apple',{name:'lucy',age:18}]
console.log(arr.slice(0, 0)); //[]
console.log(arr.slice(0, 1)); //[123]
console.log(arr); //[123,'apple',{name:'lucy',age:18}]
console.log(arr.slice(-2)); //['apple',{name:'lucy',age:18}]
console.log(arr.slice(-2, -1)); //['apple']
arr.splice(index,howmany,item1,item2...)
- 原数组从引脚
index
处删除howmany
个元素,并且用item1...
代替这些被删除的元素。 - 返回这些被删除的元素(用数组形式)。如果
index
为负值,则从数组末尾开始删除。 - 如果
howmany
值是0,则不会删除元素,我们可以利用这一特性在数组中间部位插入元素。 - 该方法是直接在原数组身上修改,这一点和
arr.slice()
不同。它们的相同点是都返回选定的元素。 - 由于
arr.unshift()
有兼容性问题,我们可以用arr.splice(0,0,item1,...)
代替,来在首位添加元素。
var test = [123, 'apple', {
name: 'lucy',
age: 18
}];
var arr = [123, 'apple', {
name: 'lucy',
age: 18
}];
console.log(test.splice(0)); //[123,'apple',{name:'lucy',age:18}]
console.log(test); //[] 被删完了
console.log(arr.splice(1, 0)); //[] 返回截取(删除)的元素
console.log(arr); //[123,'apple',{name:'lucy',age:18}]
console.log(arr.splice(0, 0, 'lily')); //[] 返回截取(删除)的元素
console.log(arr); //['lily',123,'apple',{name:'lucy',age:18}] 没有删除元素,并且在首位还添加了一个元素
console.log(arr.splice(2, 2, 'poly')); //['apple',{name:'lucy',age:18}] 返回截取(删除)的元素
console.log(arr); //['lily',123,'poly']
console.log(arr.splice(-2)); //[123,'poly'] 返回截取(删除)的元素
console.log(arr); //['lily']
arr.concat(arrayX,arrayX...)
- 连接一个或多个数组,原数组不会改变,返回一个新数组。
- 如果要进行
concat()
操作的参数是一个数组,那么添加的是该数组中的每一个元素。 - 如果添加的数组没有声明,可直接连接元素,添加在数组末尾,相当于
arr.push()
,但返回的是一个新数组。
var test = ['good', 789];
var arr = [123, 'apple', {
name: 'lucy',
age: 18
}];
//如果添加的数组没有声明,可直接连接元素,添加在数组末尾,相当于arr.push(); 但返回的是一个新数组;
console.log(arr.concat('abcdef', 'lily', 456)); //[123, "apple", {name:'lucy',age:18}, "abcdef", "lily", 456]
console.log(arr); //[123, "apple", {name:'lucy',age:18}]
//数组添加自身
console.log(arr.concat(arr)); //[123, "apple", {name:'lucy',age:18}, 123, "apple", {name:'lucy',age:18}]
console.log(arr); //[123, "apple", {name:'lucy',age:18}]
console.log(arr.concat(test)); //[123, "apple", {name:'lucy',age:18}, "good", 789]
console.log(arr); //[123,'apple',{name:'lucy',age:18}]
arr.fill(value, start, end)
- 用一个固定值填充一个数组中从起始索引到终止索引内的全部元素。
- 直接修改原数组并返回。
- start:可选 起始索引,默认值为
0
。 - end:可选 终止索引,默认值为
this.length
。
let arr1 = [1, 2, 3];
let arr2 = [1, 2, 3];
let arr3 = [1, 2, 3];
let arr4 = [1, 2, 3];
let arr5 = [1, 2, 3];
let arr6 = [1, 2, 3];
let newarr = arr1.fill(7);
console.log(arr1); //[7, 7, 7]
console.log(newarr); //[7, 7, 7]
arr2.fill(4);
console.log(arr2); // [4, 4, 4]
arr3.fill(4, 1);
console.log(arr3); // [1, 4, 4]
arr4.fill(4, 1, 2);
console.log(arr4); // [1, 4, 3]
arr5.fill(4, 1, 1);
console.log(arr5); // [1, 4, 3]
arr6.fill(4, 3, 3);
console.log(arr6); // [1, 2, 3]
数组排序
arr.reverse()
- 颠倒数组中元素的顺序。
- 直接在原数组身上修改。
var arr = [123,'apple',{name:'lucy',age:18}];
console.log(arr.reverse());//[{name:'lucy',age:18}, "apple", 123]
arr.sort( 函数 )
- 对数组的顺序进行排序。
- 直接在原数组身上修改。
- 默认按照字符编码的顺序进行排序,如果想按照其他标准进行排序,就需要提供比较函数,该函数要比较两个值,然后返回一个用于说明这两个值的相对顺序的数字。
- 比较函数应该具有两个参数
a
和b
,其返回值如下:- 若
a > b
, 即a - b > 0
,则返回一个大于0
的值,数组将按照降序排列,即a b
升序。 - 若
a < b
,即a - b < 0
,则返回一个小于0
的值,数组将按照升序排列,即b a
降序。 - 若
a = b
,则返回0
,顺序不变。
- 若
var arr = [123, 'apple', {
name: 'lucy',
age: 18
}, 456, 1456, 'banana'];
console.log(arr.sort()); //[123, 1456, 456, Object, "apple", "banana"]
var numSortCompare = function (a, b) {
if (a > b) {
return 1;
} else if (a < b) {
return -1;
} else {
return 0;
}
// 三元写法 return a > b ? (1 : a < b ? -1 : 0) : 0
}
var sortTest1 = [123, 'apple', {
name: 'lucy',
age: 18
}, 456, 1456, 'banana'];
console.log(sortTest1.sort(numSortCompare)); //[123, Object, "apple", 456, 1456, "banana"]
// 按编码顺序排序
var sortTest2 = [1, 1043, 78, 1043, -98, 652, 0, 205, 205];
console.log(sortTest2.sort()); //[-98, 0, 1, 1043, 1043, 205, 205, 652, 78]
// 按数值大小排序,小的在前
var sortTest3 = [1, 1043, 78, 1043, -98, 652, 0, 205, 205];
console.log(sortTest3.sort(numSortCompare)); //[-98, 0, 1, 78, 205, 205, 652, 1043, 1043]
// 按数值大小排序,大的在前
// 这里我们一般不改函数,而是先比较,然后再反向;
var sortTest4 = [1, 1043, 78, 1043, -98, 652, 0, 205, 205];
console.log(sortTest4.sort(numSortCompare).reverse()); //[1043, 1043, 652, 205, 205, 78, 1, 0, -98]
数组查找
arr.indexOf(find,start)
- 来定位数组中某指定元素首次出现的位置(返回索引),如果没找到返回
-1
。 start
是从哪个位置开始找;如果没有就是默认从0
开始。arr.indexOf()
只有在IE9+
有效,在IE8
中右兼容性问题。arr.indexOf()
和string.indexOf()
类似。
var arr = [123, 'apple', {
name: 'lucy',
age: 18
}, 456, 1456, 'banana'];
console.log(arr.indexOf(456)); //3
console.log(arr.indexOf('apple')); //1
console.log(arr.indexOf(456, 5)); //-1
console.log(arr.indexOf('sss')); //-1
//非0为true;0为false; 所以这里-1也为true;
if (arr.indexOf('sss')) {
console.log('没找到sss');
}
//arr.indexOf()兼容处理如下
if (typeof Array.prototype.indexOf != "function") {
Array.prototype.indexOf = function (searchElement, fromIndex) {
var index = -1;
fromIndex = fromIndex * 1 || 0;
for (var k = 0, length = this.length; k < length; k++) {
if (k = fromIndex && this[k] === searchElement) {
index = k;
break;
}
}
return index;
};
}
arr.lastIndexOf(find,start)
- 来定位数组中某指定元素最后一次出现的位置(返回索引),如果没找到返回
-1
。 start
是从哪个位置开始找;indexOf
的逆向查找,即从数组最后一个往前查找。如果没有就是默认从length-1
开始。
var arr = [123, 'apple', {
name: 'lucy',
age: 18
}, 456, 1456, 'apple', 'banana'];
console.log(arr.lastIndexOf('apple')); //5
//arr.lastIndexOf()兼容处理如下
if (typeof Array.prototype.lastIndexOf != "function") {
Array.prototype.lastIndexOf = function (searchElement, fromIndex) {
var index = -1,
length = this.length;
fromIndex = fromIndex * 1 || length - 1;
for (var k = length - 1; k -1; k -= 1) {
if (k <= fromIndex && this[k] === searchElement) {
index = k;
break;
}
}
return index;
};
}
arr.includes(searchElement, fromIndex)
includes()
方法用来判断一个数组是否包含一个指定的值,如果是返回true
,否则false
。- 对象数组不能使用
includes
方法来检测。
var test = {
name: 'Jim',
age: 22
}
var arr = [123, 'apple', {
name: 'lucy',
age: 18
}, 456, 1456, test, 'banana'];
console.log(arr.includes('banana')); //true
console.log(arr.includes({
name: 'lucy',
age: 18
})); //false 对象数组不能使用`includes`方法来检测。
console.log(arr.includes(test)); //true
arr.find((value, index, arr) => {},thisValue)
- 返回符合条件的第一个元素的值,之后的值不会再调用执行函数。
- 如果没有符合条件的元素返回
undefined
。
var test = {
name: 'Jim',
age: 22
}
var arr = [123, 'apple', {
name: 'lucy',
age: 18
}, 456, 1456, test, 'banana'];
console.log(arr.find(i => i == 'banana')); //banana
console.log(arr.find(i => i == test)); //{name: "Jim", age: 22}
console.log(arr.find(i => i.age == 18)); //{name: "lucy", age: 18}
console.log(arr.find(i => i == {
name: 'lucy',
age: 18
})); //undefined
arr.findIndex((value, index, arr) => {}, thisValue)
- 返回符合条件的第一个元素位置,之后的值不会再调用执行函数。
- 如果没有符合条件的元素返回
-1
。
var test = {
name: 'Jim',
age: 22
}
var arr = [123, 'apple', {
name: 'lucy',
age: 18
}, 456, 1456, test, 'banana'];
console.log(arr.findIndex(i => i == 'banana')); //6
console.log(arr.findIndex(i => i == test)); //5
console.log(arr.findIndex(i => i.age == 18)); //2
console.log(arr.findIndex(i => i == {
name: 'lucy',
age: 18
})); //-1
数组遍历
arr.forEach((value,index,arr) => {},[thisObject])
forEach
方法中的回调函数支持3个参数(遍历的数组元素,该索引,数组本身)。[thisObject]
为可选参数,可改变回调函数的this
指向。forEach
不会遍历空的元素。- 理论上这个方法是没有返回值的,仅仅是遍历数组中的每一项,不对原来数组进行修改。但是可以自己通过数组的索引来修改原来的数组。
var test1 = [123, 'apple', , {
name: 'lucy',
age: 18
}];
test1.forEach(console.log);
//结果如下,注意没有索引为2的元素
//123 0 [123, "apple", Object]
//apple 1 [123, "apple", Object]
//Object {name: "lucy", age: 18} 3 [123, "apple", Object]
var sum = 0;
test1.forEach((value, index, arr) => {
sum += value;
})
console.log(sum); //123apple[object Object]
function titleCase(str) {
var newarr = str.toLowerCase().split(" ");
newarr.forEach((i, k) => {
newarr[k] = i.replace(i.charAt(0), i.charAt(0).toUpperCase());
})
return newarr.join(" ");
}
console.log(titleCase("I'm a javascript coder")) //I'm A Javascript Coder
//IE6-IE8兼容性写法
if (typeof Array.prototype.forEach != "function") {
Array.prototype.forEach = function (fn, context) {
for (var k = 0, length = this.length; k < length; k++) {
if (typeof fn === "function" && Object.prototype.hasOwnProperty.call(this, k)) {
fn.call(context, this[k], k, this);
}
}
};
}
arr.map((value,index,arr) => {},[thisObject])
- 在实际使用中,我们可以用
arr.map()
得到数组中特定的属性值。 map
的回调函数中支持return
返回值。相当于把数组中的这一项变为return
的值(并不影响原数组,只是相当于把原数组克隆一份,把克隆的这一份的数组中的对应项改变了)。
var arr = [{
name: 'lily',
age: '16'
}, {
name: 'meno',
age: '18'
}, {
name: 'jim',
age: '17'
}];
var ageData = arr.map((value) => {
return value.age;
})
console.log(ageData); //['16','18','17']
//IE6-IE8兼容性写法
if (typeof Array.prototype.map != "function") {
Array.prototype.map = function (fn, context) {
var arr = [];
if (typeof fn === "function") {
for (var k = 0, length = this.length; k < length; k++) {
arr.push(fn.call(context, this[k], k, this));
}
}
return arr;
};
}
arr.filter((value,index,arr) => {},[thisObject])
- 遍历所有元素,返回一个新数组,新数组包含符合条件的所有元素。
var test1 = [123, 'apple', , {
name: 'lucy',
age: 18
}];
var ageData = test1.filter(value => value.age > 10)
console.log(ageData); //[{name: "lucy", age: 18}]
//IE6-IE8兼容性写法
if (typeof Array.prototype.filter != "function") {
Array.prototype.filter = function (fn, context) {
var arr = [];
if (typeof fn === "function") {
for (var k = 0, length = this.length; k < length; k++) {
fn.call(context, this[k], k, this) && arr.push(this[k]);
}
}
return arr;
};
}
arr.some((value,index,arr) => {},[thisObject])
- 检测数组中的元素是否存在满足指定条件的元素。只要有
1
个返回true
,后面就不执行了。 - 返回
Boolean
。
var test1 = [123, 'apple', , {
name: 'lucy',
age: 18
}];
//验证所有元素中是否存在age属性,存在返回true,只要验证到存在1个,后面就不继续验证了
var ageData = test1.some(value => value.age)
console.log(ageData); //true
//IE6-IE8兼容性写法
if (typeof Array.prototype.some != "function") {
Array.prototype.some = function (fn, context) {
var passed = false;
if (typeof fn === "function") {
for (var k = 0, length = this.length; k < length; k++) {
if (passed === true) break;
passed = !!fn.call(context, this[k], k, this);
}
}
return passed;
};
}
arr.every((value,index,arr) => {},[thisObject])
- 验证所有元素,都满足条件,才返回
true
。 - 如果数组中检测到有一个元素不满足,则整个表达式返回
false
,且剩余的元素不会再进行检测。
var test1 = [123, 'apple', , {
name: 'lucy',
age: 18
}];
//验证所有元素中是否都存在age属性,只要有1个不存在,就返回false,
var ageData = test1.every(function (value) {
return value.age;
})
console.log(ageData); //false
var ageData2 = test1.every(value => value.age)
console.log(ageData2); //false
var test2 = [5, 6, 7, 8, 9];
var bigger4 = test2.every((value) => {
return value > 4;
})
console.log(bigger4); //true
//IE6-IE8兼容性写法
if (typeof Array.prototype.every != "function") {
Array.prototype.every = function (fn, context) {
var passed = true;
if (typeof fn === "function") {
for (var k = 0, length = this.length; k < length; k++) {
if (passed === false) break;
passed = !!fn.call(context, this[k], k, this);
}
}
return passed;
};
}
arr.reduce((previous,current,index,array) => {},initialValue)
- 接收一个方法作为累加器,数组中的每个值(从左至右) 开始合并,最终为一个值。
callback
有4个参数(previous,current,index,array)
,previous
为初始值, 或者计算结束后的返回值,current
为当前元素,index
索引,array
数组本身。iniaialValue
为可选参数,表示初始值,如果设置了这个值,就是最初的previous
值,current
为之后的元素;如果没有设置,则previous
值为数组第一个元素,current
为第二个元素。
var test1 = [123, 'apple', , {
name: 'lucy',
age: 18
}];
var testData1 = test1.reduce((presious, current) => {
return presious + current;
})
console.log(testData1); //123apple[object Object]
console.log(typeof testData1); //string
//二维数组扁平化
var test2 = [
[2, 3, 4],
[5, 6, 7, 8, 9],
['apple'],
[345, 'banana']
];
var testData2 = test2.reduce((previous, current) => {
return previous.concat(current);
})
console.log(testData2); //[2, 3, 4, 5, 6, 7, 8, 9, "apple", 345, "banana"]
//IE6-IE8兼容性写法
if (typeof Array.prototype.reduce != "function") {
Array.prototype.reduce = function (callback, initialValue) {
var previous = initialValue,
k = 0,
length = this.length;
if (typeof initialValue === "undefined") {
previous = this[0];
k = 1;
}
if (typeof callback === "function") {
for (k; k < length; k++) {
this.hasOwnProperty(k) && (previous = callback(previous, this[k], k, this));
}
}
return previous;
};
}
for...in 和 for...of
for...in
的方式遍历的是数组中的索引,前面也提到过数组是一种特殊的对象,在默认的情况下是以0...n
的数字作为索引,但是也可以用其他字符作为索引,所以当数组中存在其他索引的时候可以用for...in
获取。- 当我们手动给
Array
对象添加了额外的属性后,for … in
循环将带来意想不到的意外效果。 for ... of
直接遍历数组中的值。
var arr = ['a','b','c'];
arr.k = "hello";
for(let i in arr){
console.log(i+":"+arr[i]); //遍历的是属性值
}
/*
0:a
1:b
2:c
k:hello
*/
console.log(arr); // [ 'a', 'b', 'c', k: 'hello' ]
var arr2 = ['a','b','c'];
arr2.k = "hello";
for(let val of arr2){
console.log(val);
}
/*
a
b
c
*/
判断变量是否为数组
Array.isArray(testData)
var arr = [123, 'apple', {
name: 'lucy',
age: 18
}, 456, 1456, 'banana'];
console.log(Array.isArray(arr)); //true
//isArray在IE9+有效,考虑其兼容性,比较好的方法如下:
function isArrayFn(value) {
if (!Array.isArray){
Array.isArray = function(arg){
return Object.prototype.toString.call(arg) === '[object Array]';
};
}
}
console.log(isArrayFn(arr)); //true