数组用于在单个变量中存储多个值。数组是一个特殊变量,一次可以包含多个值,并且还可以通过引用索引号来访问这些值。
数组是一种类列表对象,它的原型中提供了遍历和修改元素的相关操作。JavaScript 数组的长度和元素类型都是非固定的。因为数组的长度可随时改变,并且其数据在内存中也可以不连续,所以 JavaScript 数组不一定是密集型的,这取决于它的使用方式。
创建数组的方式
使用字面量形式创建
var array_1 = ['apple', 'banner', 'orange', 'pear', 'Mongo'];
使用关键字创建
// 当关键字括号内有多个已逗号分开的项的话,代表创建数组的项
var array_1 = new Array('apple', 'banner', 'orange', 'pear', 'Mongo');
// 当关键字括号内只有一个值,并且是正数的话,表示创建一个有n个为空的数组项
var array_2 = new Array(10);
// 上边的代码创建了一个有10个空项的数组
var array_3 = new Array(-10);
var array_4 = new Array(4294967296);
// Uncaught RangeError: Invalid array length
// 上边的两种定义数组都会无效的数组长度错误,
// 如果使用 new 关键字创建数组的话,并且括号中只有一个值,且值为数值类型的情况下,取值范围是:
// 0 到4294967295 也就是2的32次方 = 4294967296 -1的正数
一般建议使用字面量形式创建数组,原因是字面量形式创建数组简单,并且不会出现array_2
的那种情况
访问数组元素, 给数组项赋值
// 访问数组元素
var firstItem = array_1[0]; // apple
// 给数组的元素赋值
array_1[0] = 20;
数组的属性
length
length
是Array实力中的一个属性,用来返回或者设置一个数组的元素个数,改值是一个32-bit
位的整正数。并且此值总是数组最高位的下标+1
var array_1 = ['apple', 'banner', 'orange', 'pear', 'Mongo'];
var sum = array_1.length; // 5
我们也可以通过设置该属性值得方式来截断或者增加数组的项
var array_1 = ['apple', 'banner', 'orange', 'pear', 'Mongo'];
// 当我们把数组的length属性设置成小于数组个数的值时,会把下标大于该值的所有元素截取掉,直接改变当前数组
array_1.length = 3; // (3) ['apple', 'banner', 'orange']
// 当我们把数组的length属性设置成大于数组个数的值时,会自动往数组后边追加n个空项。
array_1.length = 10; // (10) ['apple', 'banner', 'orange', 空属性 × 7]
// 如果把length 设置成大于 2的32方,小于0,并且是非正整数的值都会报错
lengthArray_1.length = 4294967296;
lengthArray_1.length = -1
数组的静态方法
数组的静态方法是直接定义在
Array
上,并且通过Array.
的方式进行调用
Array.from()
从一个可迭代的元素对象中创建一个新数组,并且他是浅拷贝的
语法:
Array.from(arrayLike[, mapFn[, thisArg]]);
参数:
arrayLike
需要转行数组的可迭代的元素mapFun
转换成数组后为数组每一项执行该函数并返回最新thisArg
执行mapFn 的时候mapFn函数内部的this
指向
示例:
基本用法:
function fn(){
// 使用Array.from将参数(arguments)类数组转换成真正的数组
return Array.from(arguments);
}
let newArr = fn('apple', 'banner', 'orange', 'pear', 'Mongo');
// (5) ['apple', 'banner', 'orange', 'pear', 'Mongo']
// 把获取dom节点的集合类数组改成数组,由于获取dom得到的是一个nodeList的类数组的dom集合
let domNodeList = document.querySelectorAll('span');
// 原始数据: NodeList(10) [span, span, span, span, span, span, span, span, span, span]
let domArr = Array.from(domArr);
// 转换后的数据: (10) [span, span, span, span, span, span, span, span, span, span]
// 由于字符串页带有length属性,也是可以进行迭代的,所以from可以把字符串的每个个字符单独分开转换成数组
let str = Array.from('hello world');
// (11) ['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd']
// 我们还可以把带length属性的对象转换成数组
let parson = {name: 'qwguo', sex: '男', age: 30, length: 3};
Array.from(parson)
// (3) [undefined, undefined, undefined]
// 这里转换后的值是三个undefined项的数组,是因为上边的person对象length值为3,但是他并没有0-2的键值的数据
let parson2 = {0: 'qwguo', 1: '男', 2: 30, length: 3};
Array.from(parson2);
// (3) ['qwguo', '男', 30]
// parson2对象设置了length键值,并且把每一项以数组为键值存储,这样就可以通过from方法转换成数组类型
let parson3 = {0: 'qwguo', 1: '男', 2: 30};
Array.from(parson3);
// []
// 由于对象并没有设置length属性所以默认取值为0
// ES6新增的数据类型,Set数据类型,Map数据类型,本身就是可以迭代的,所以可以调用from方法将其转换成数组
// Set数据类型转换成数组
var newSet = new Set(['foo', 'bar', 'baz', 'foo'])
console.log('原set数据:', newSet);
// 原set数据:Set(3) {'foo', 'bar', 'baz'}
// 因为本身ES6的Set类型的数据项具有唯一性,所以会把重复的数据剔除掉
console.log('把set数据转换成数组:', Array.from(newSet));
// (3) ['foo', 'bar', 'baz']
// Map数据类型转换成数组
const mapper = new Map([['1', 'a'], ['2', 'b']]);
console.log('map元数据:', mapper);
// map元数据: Map(2) {'1' => 'a', '2' => 'b'}
console.log('map数据转换成数组', Array.from(mapper));
// (2) [Array(2), Array(2)]
// 可以通过Map的values 、keys方法分别得到键和值的数组集合
console.log('map.values方法只转换值为数组:', Array.from(mapper.values()));
// (2) ['a', 'b']
console.log('map.values方法只转换键为数组:', Array.from(mapper.keys()));
// (2) ['1', '2']
mapFun方法使用:
function fn2(){
// 把函数接收的参数转换数组
return Array.from(arguments, (v, i)=>{
return v = v + '_++';
});
}
let newArr2 = fn2('apple', 'banner', 'orange', 'pear', 'Mongo');
console.log('把函数参数转换成数组:', newArr2);
// (5) ['apple_++', 'banner_++', 'orange_++', 'pear_++', 'Mongo_++']
// 我们可以利用对象有length转换成数组的特性,在运行map方法生成一个0-n的数值序列数组
let numArr = Array.from({length: 5}, (v, i) => i);
//(5) [0, 1, 2, 3, 4]
mapFun类似于数组的map方法,相当于把转换后的数组调用一遍map方法
通过上边的知识我们可写一个生成数字数组的生成器
function numRange(start, end, step){
return Array.from({length: (end - start) / step + 1}, (v, i) => start + i * step);
}
console.log(numRange(1, 10, 1));
// (10) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
console.log(numRange(1, 10, 4));
// (3) [1, 5, 9]
// 生成A-Z的字母数组,先通过上边的方法获取A-Z之间的charCodeAt码数组,然后在使用数组的map进行处理成对象的字母返回
numRange('A'.charCodeAt(), 'Z'.charCodeAt(), 1).map(function(v, i){return String.fromCharCode(v)})
第三个参数是用来改变第二个参数的map方法调用时候的内部this执行的参数
function fn3(){
// 把函数接收的参数转换数组
let y = {z: 20};
return Array.from(arguments, function(v, i){
console.log(this);
return v = v + '_++';
});
}
// 这种情况调用fn3的话,map内部的this指向的是window,因为是在window下调用的该
let newArr3 = fn3('apple', 'banner', 'orange', 'pear', 'Mongo');
//如果通过这种方式调用this指向的还是window,虽然这调用fn3方法时改变了this,但是map方法的执行并没有改变this
let x = {a: 10, b: 20};
fn3.call(x, 'apple', 'banner', 'orange', 'pear', 'Mongo');
// 把上边的方法改成如下代码
function fn4(){
// 把函数接收的参数转换数组
let y = {z: 20};
return Array.from(arguments, function(v, i){
console.log(this);
return v = v + '_++';
}, this);
}
let x = {a: 10, b: 20};
fn4.call(x, 'apple', 'banner', 'orange', 'pear', 'Mongo');
// 这个时候调用map内部的this就指向了调用该方法的this了,我们也可以传入上边的y把this指向改变为y对象
// 这里还需要注意的是,如果把map方法换成箭头函数的话,由于箭头函数没有this,所以内部的this执行调用该方法的this,就相当于上边第三个参数传this值
Array.isArray()
用于检测传递的参数是否是数组,它也是Array上的一个静态方法
语法
Array.isArray(obj)
obj
:需要检测的对象
如果是数组返回 true
否则返回 false
示例
let objArr = {0: 'qwguo', 1: '30', 2: '男', length: 3}
console.log(Array.isArray(objArr));
// false
console.log(Array.isArray(Array.from(objArr)));
// true
let spanDom = document.querySelectorAll('span');
console.log(Array.isArray(spanDom));
// false
let arr = [10, 20, 30];
console.log(Array.isArray(arr));
// true
兼容写法
// 判断Array类上有没有isArray静态方法
if(!Array.isArray){
Array.isArray = function(arg){
// 通过是用Object.prototype.toString.call的方式可以得到对象的具体是什么类型
return Object.prototype.toString.call(arg) === '[object Array]';
}
}
Array.of()
该方法是用来创建一个给定参数的新数组,和
new Array()
类似,唯一的区别是解决了传递一个整正数参数的时候创建非想要的结果的问题
语法
Array.of(element0[, element1[, ...[, elementN]]])
示例
var newArr_1 = new Array(7);
console.log(newArr_1);
//(7) [空属性 × 7]
var newArr_2 = Array.of(7);
console.log(newArr_2);
// [7]
兼容写法
if(!Array.of){
Array.of = function(){
return Array.prototype.slice.call(arguments);
}
}
数组原型上的方法
array.at()
数组的
at()
方法是用来访问数组中的元素,和我们正常访问数组元素使用的array[index]
效果一样,唯一的区别是at可以传递一个负数,表示从数组最后边向前查找
语法示例:
let array_1 = [10, 5, 'apple', 'banner', 'orange', 'pear'];
console.log(array_1.at(2));
// apple
console.log(array_1.at(-6));
// orange
兼容写法
// 兼容写法
if(!Array.prototype.at){
Array.prototype.at = function(index) {
// 通过判断传过来的索引是否小于0,如果小于0,就用数组当前的length 加上索引值,就能得到从后向前的查找效果
index = index < 0 ? this.length + index : index;
return this[index];
}
console.log(array_1.at(-7));
}
array.concat()
concat
方法,合并两个数组或多个数组,生成一个新数组, 该方法并不会改变任何一个原数组
语法
array.concat(array_2, array_3, array_4,...,array_n);
// array,可以是一个空数组,或者是要合并的数组的其中一个
// 参数:为一个或多个数组,或者是任意类型的值
示例
var number_arr = [10, 20, 5, 8, 12, 30];
var fruit_arr = ['apple', 'banner', 'orange', 'pear'];
var animal_arr = ['dog', 'cat', 'sheep', 'chicken', 'horse', 'cow'];
let concat_arr = number_arr.concat(fruit_arr, animal_arr);
//合并后的数组: (16) [10, 20, 5, 8, 12, 30, 'apple', 'banner', 'orange', 'pear', 'dog', 'cat', 'sheep', 'chicken', 'horse', 'cow']
let concat_str_arr = [].concat('new_val', 100, undefined, null, NaN, {a:10}, fruit_arr);
// (10) ['new_val', 100, undefined, null, NaN, {…}, 'apple', 'banner', 'orange', 'pear']
array.copyWithin
复制数组中的某部分内的数据到另外某个部分,此方法不会改变原数组的长度,但是会改变原数组
语法
array.copyWithin(target, start, end)
参数说明:
target
: 必填要传递的参数,表示目标位置,取值范围:必须是整数。如果取值为0的话,如果不传不执行任何操作start
:要拷贝的数据的开始索引值,可以是负数,如果为负数那么就从数组末尾开始计算,可以用length + start,如果不传默认从数组第一个值开始到目标位置end
: 要拷贝的数组的结束索引,并不包括该索引下的值;
示例
let arr_1 = ['a', 'b', 'c', 'd', 'e', 'f', 'g'].copyWithin(2);
// (7) ['a', 'b', 'a', 'b', 'c', 'd', 'e']
let arr_2 = ['a', 'b', 'c', 'd', 'e', 'f', 'g'].copyWithin(3, 4);
// (7) ['a', 'b', 'c', 'e', 'f', 'g', 'g']
let arr_3 = ['a', 'b', 'c', 'd', 'e', 'f', 'g'].copyWithin(1, 4, 6);
// (7) ['a', 'e', 'f', 'd', 'e', 'f', 'g']
let arr_4 = ['a', 'b', 'c', 'd', 'e', 'f', 'g'].copyWithin(-5, -2, -1);
// (7) ['a', 'b', 'f', 'd', 'e', 'f', 'g']
let arr_5 = ['a', 'b', 'c', 'd', 'e', 'f', 'g'].copyWithin(-5, -1, 2);
// (7) ['a', 'b', 'c', 'd', 'e', 'f', 'g']
array.entries()
生成一个新的Array Iterator对象迭代器,该对象里已键值对的形式保存了数组的所有项
语法
array.entries()
示例
let arr_1 = ['a', 'b', 'c'];
let en_array = arr_1.entries();
/*Array Iterator {}
__proto__:Array Iterator
next:ƒ next()
Symbol(Symbol.toStringTag):"Array Iterator"
__proto__:Object
*/
// 我们这里可以调用next方法来输出数组中的每一项
en_array.next();
/*{value: Array(2), done: false}
done:false
value:(2) [0, "a"]
__proto__: Object
*/
// iterator.next()返回一个对象,对于有元素的数组,
// 是next{ value: Array(2), done: false };
// next.done 用于指示迭代器是否完成:在每次迭代时进行更新而且都是false,
// 直到迭代器结束done才是true。
// next.value是一个["key","value"]的数组,是返回的迭代器中的元素值。
// 使用for of 形式输出
for(i of en_array){
console.log(i);
}
// (2) [1, 'b']
// (2) [2, 'c']
// 由于上边调用过一次next方法,所以这个时候在执行for of 就会从next的下一个开始循环
// 其中i是每一项的数组
array.every()
迭代数组中的每一个元素,并且为数组中的每一个元素执行以下回调方法判断是否符合给定的条件,只有数组的所有元素都满足条件
every
方法返回true
,如果有一个不满足就返回false
,ie9以上支持
语法
array.every(callBack(element, index, array), this)
参数
callBack
:为数组项中的每一项执行的回调函数element
: 循环数组中的每一项index
: 当前数组项的下标array
: 当前的循环你数组
this
: 回调函数内部的this指向,如果是箭头函数的情况下这里传入的this并不会改变,callBack中的this执行的是window
示例
let array_1 = [20, 3, 15, 40, 2, 50, 70];
array_1.every(function(v, i, arr){
return v > 10;
});
// false
let mark_2 = array_1.every(function(v, i, arr){
return v > 1;
});
// true
// 这里需要说明
let mark_3 = array_1.every(function(v, i, arr){
console.log(i, v);
if(i === 0){
// 当我们在遍历的时候动态给数组增加元素的时候,every的回调函数并不会执行新增加的元素
arr.push(100);
// 当我们修改已经存在的元素的时候,或者删除某个元素的时候,every的回调函数会拿到新修改的值
arr.splice(1, 1, 60)
}
return v > 1;
});
console.log(mark_3);
// true
兼容写法
Array.prototype.every = function(callBack, thisArg){
let arr = this;
let leg = arr.length;
for(let i = 0; i < leg; i++){
if(!callBack.call(thisArg, arr[i], i, arr)){
return false;
}
}
return true;
}
array.fill
用某个值填充数组从开始到结束的所有项,会更改原数组,但是不会更改数组的长度,IE浏览器暂不支持
语法
array.fill(value, start, end);
参数
value
:需要填充的值,可以是任意值,如果不传入,那么取值是undefinedstart
:开始填充的位置必须是整数, 可选参数,如果不传默认从第一个值开始, 如果是负数的话,将要从后往前查找相当于array.length + start
end
:结束填充的位置必须是整数,可选参数如果不传表示到数组的最后一个值, 规则同start相同
示例
let arr = ['a', 'b', 'c', 'd'];
[].concat(arr).fill();
// (4) [undefined, undefined, undefined, undefined],不传任何参数,将把数组的所有项替换成undefined
[].concat(arr).fill(10);
// (4) [10, 10, 10, 10],值传入第一个值将把该值替换到所有的数组项中
[].concat(arr).fill(10, 2);
// (4) ['a', 'b', 10, 10],只传入两个值,前边的表示替换后的值,然后从start开始到数组末尾
[].concat(arr).fill(10, 0, 2);
//(4) [10, 10, 'c', 'd'],把数值10替换到数组从第一项开始到第二项的项目,不包括第三个
[].concat(arr).fill(3, -2, -1);
//(4) ['a', 'b', 3, 'd'],把数值3替换到从 array.length(4) + -2 = 2,到array.length(4) + -1 = 3的位置,
[].concat(arr).fill([3, 10], 1, 4);
// (4) ['a', Array(2), Array(2), Array(2)] // 替换的值可以是数组
[].concat(arr).fill(NaN, 1, 4);
// (4) ['a', NaN, NaN, NaN]
let j = {a: 10};
[].concat(arr).fill(j, 1, 4);
// (4) ['a', {…}, {…}, {…}], 这里替换的下标为第1个到下标4个的项,因为这里替换的是对象所以他们都指向一个对象j, 当改变j的内部数据是,替换的项会跟随变化
j.a = 30;
兼容写法
if(!Array.prototype.fill){
Array.prototype.fill = function(){
let arr = this;
let len = arr.length;
let val = arguments[0];
let start = arguments[1];
let end = arguments[2];
if(start){
if(start < 0)
start = len + start;
}else{
start = 0
}
if(end){
if(end < 0){
end = len + end;
}
}else{
end = len;
}
while(start<end){
arr[start] = val;
start++;
}
return arr;
}
}
array.filter()
数组过滤器,循环数组中的每一项,然后为每一项调用回调函数进行判断,然后返回符合条件的项,生成新数组, IE9以上支持
语法
let newArray = array.filter(callBack(element, index, array), thisArg);
参数
callBack
:为每个元素执行的回调函数,回调函数中进行判断,如果条件成立返回true,保留当前项,如果条件不成立返回false排除当前项,如果没有找到匹配的项返回空数组element
:循环迭代的每一项index
:当前项的下标索引值array
:循环的当前数组
thisArg
:用于改变回调函数中的this指向
示例
let array = [10, 20, 5, 3, 80, 6, 1, 12];
let newArray_1 = array.filter((element, index, arr)=>{
return element > 10;
});
// (3) [20, 80, 12]
let newArray_2 = array.filter((element, index, arr)=>{
return index%2;
});
// (4) [20, 3, 6, 12]
let array_2 = ['apple', 'banana', 'grapes', 'mango', 'orange'];
let fun = function(e, i, arr){
return e.indexOf('ap') != -1;
};
let newArray_3 = array_2.filter(fun);
// (2) ['apple', 'grapes']
兼容写法
if(!Array.prototype.filter){
Array.prototype.filter = function(callBack, thisArg){
if(typeof(callBack) !== 'function'){
throw new TypeError(callBack + ' is not a function');
return;
}
let newArr = [];
let arr = this;
let len = arr.length;
let i = 0;
while(i<len){
if(callBack.call(thisArg, arr[i], i, arr)){
newArr.push(arr[i]);
}
i++;
}
return newArr;
}
}
array.find()
循环迭代数组中的项目,并且提供一个函数作为检测函数,如果数组中有一项满足检测条件就返回匹配的第一个值并且直接退出循环,如果没找到返回
undefined
语法
array.find(callBack(element, index, arr), thisArg);
参数
callBack
:循环迭代为每个元素执行的回调函数,回调函数中进行判断,如果条件成立返回当前项并且结束循环,只要循环中找到一个匹配项立马结束循环,如果没有匹配的项返回undefinedelement
:循环迭代的每一项index
:当前项的下标索引值array
:循环的当前数组
thisArg
:用于改变回调函数中的this指向
示例
let array = [10, 20, 5, 3, 80, 6, 1, 12];
console.log('原数组:', array);
let newArray_1 = array.find((element, index, arr)=>{
return element > 60;
});
// 80
let newArray_2 = array.find((element, index, arr)=>{
return index%2;
});
// 20
let array_2 = ['apple', 'banana', 'grapes', 'mango', 'orange'];
let fun = function(e, i, arr){
return e.indexOf('ap') != -1;
};
let newArray_3 = array_2.find(fun);
// apple
兼容写法
if(!Array.prototype.find){
Array.prototype.find = function(callBack, thisAge){
let arr = this, len = arr.length, i = 0;
while(i<len){
if(callBack.call(thisAge, arr[i], i, arr)){
return arr[i];
}
i++;
}
}
}
array.findIndex()
此方法和find类似他是通过迭代循环数组中的每一项,然后为每一项调用函数进行测试,并且返回符合条件的那一项的索引值
语法
array.findIndex(callBack(element, index, arr), thisArg)
参数
callBack
:循环迭代为每个元素执行的回调函数,回调函数中进行判断,如果条件成立返回当前项的索引下标并且结束循环,只要循环中找到一个匹配项立马结束循环,如果没有匹配的项返回-1element
:循环迭代的每一项index
:当前项的下标索引值array
:循环的当前数组
thisArg
:用于改变回调函数中的this指向
兼容写法
if(!Array.prototype.findIndex){
Array.prototype.findIndex = function(callBack, thisAge){
let arr = this, len = arr.length, i = 0;
while(i<len){
if(callBack.call(thisAge, arr[i], i, arr)){
return i;
}
i++;
}
return -1;
}
}
array.flat()
扁平化一个数组,把多维数组转换成给定参数的层级数组,此方法并不会改变原数组,而是返回一个新数组
语法
array.flat([depth])
参数
depth
:可选参数,表示希望把当前的多为数组结构多少层,如果给的的参数大于数组的最大深度,那么将把数组转换成一维数组,如果不指定,那么只是把数组中的二维拆成一维。
示例
const array = [0, 1, 2, [3, 4, [5, 6, [7, 8]]], 20, [30, 31, 32, [33, 34]]];
console.log(array.flat());
// (11) [0, 1, 2, 3, 4, Array(3), 20, 30, 31, 32, Array(2)]
// 只结构一层
console.log(array.flat(2));
// (14) [0, 1, 2, 3, 4, 5, 6, Array(2), 20, 30, 31, 32, 33, 34]
console.log(array.flat(5));
// (15) [0, 1, 2, 3, 4, 5, 6, 7, 8, 20, 30, 31, 32, 33, 34]
console.log(array.flat(-1));
// (6) [0, 1, 2, Array(3), 20, Array(4)]
// 如果参数为负数将不进行任何操作
console.log(array.flat('a'));
// (6) [0, 1, 2, Array(3), 20, Array(4)]
// 如果传入的参数为字符串,会执行Number看是否可以转换成数字,如果不能,不进行操作
console.log(array.flat(2.1));
// (14) [0, 1, 2, 3, 4, 5, 6, Array(2), 20, 30, 31, 32, 33, 34]
// 如果传入的是小数,那么将转换成整数在进行结构
console.log(array.flat('2'));
// (14) [0, 1, 2, 3, 4, 5, 6, Array(2), 20, 30, 31, 32, 33, 34]
// 字符串将进行隐试类型转换
兼容写法
if(!Array.prototype.flat){
Array.prototype.flat = function(depth){
//先判断传入的depth深度是否存在,如果没传默认值给1
depth = depth === undefined ? 1 : depth;
// 然后把传入的值转换为数值类型
depth = Number(depth);
// 然后判断是否成功转换成数字型,如果传入的不是数字,那把depth赋值为-1不进行操作,如果是数字,那么转换成整数
depth = isNaN(depth) ? -1 : parseInt(depth);
// 获取当前的数组对象
let array = this;
// 定义一个新数组用来存储返回值
let newArray = [];
// 定义递归方法
let fun = function(arr_, dep){
// 获取当前的数组项长度
let i = 0, len = arr_.length;
// 循环遍历 当前数组项
while(i < len){
// 这里使用 in 运算符可以排除数组中的空项
if(i in arr_){
// 如果深度小于等于0或者当前数组项非数组直接把当前项放到新数组中
if(dep <= 0 || Object.prototype.toString.call(arr_[i]).indexOf('Array') === -1){
newArray.push(arr_[i]);
}else{
// 如果当前项是数组,那么递归调用当前方法,并且把深度值减去1
fun(arr_[i], dep - 1);
}
}
i++;
}
}
// 调用方法并传入当前数组对象,和要扁平化的深度值
fun(array, depth);
return newArray;
}
}
array.forEach()
循环遍历数组中的每一项,为每一项执行回调函数,此方法的返回值为undefined,可以理解为没有返回值
语法
array.forEach(callBack(currentValue, index, arr), thisArg)
参数
callBack
: 遍历数组时为每次遍历提供的回调函数currentValue
表示遍历过程中的当前项;index
遍历当前项的索引下标arr
当前遍历的数组
thisArg
用于改变遍历回调函数中的this指向
示例
let array = [1, 2, 3, 4, , 5, undefined, null, NaN];
array.forEach(function(val, index, arr){
console.log(val);
});
// 1
// 2
// 3
// 4
// 5
// undefined
// null
// NaN
// 循环遍历数组,会跳过空项
兼容写法
if(!Array.prototype.forEach){
Array.prototype.forEach = function(callBack, thisAge){
// 存储当前数组对象
let array = this,
// 获取当前数组的长度,由于forEach在遍历的时候已经确定好数组长度
len = array.length,
i = 0;
//使用while循环遍历
while(i < len){
// 通过in运算符可以排除数组中的空项
if(i in array){
// 然后使用call的方式改变callBack中的this指向问题,如果thisAge没有传,默认是undefined,这是this指向window
callBack.call(thisAge, array[i], i, array);
}
i++;
}
}
}
array.includes()
方法用来判断一个数组中是否包含给定的值,如果包含返回
true
,否则返回false
, IE并不支持
语法
array.includes(findVal, fromIndex);
参数
findVal
:表示要查找的值,这里的查找比较是通过===全等的形式进行比较fromIndex
:非必填,表示从数组的哪个位置开始查找,如果给定的值大于数组的length
那么直接返回false
,如果给定的值为负数那么先进行length + fromIndex
如果计算出来的结果还是负数,那么就从第一个开始查找,也可以理解成从后往前数的位置。
示例
let array = [1, 2, 3, 4, , 5, undefined, null, NaN, true, -0];
console.log('原数组', array);
console.log("array.includes(undefined)",array.includes(undefined));
// true 这里第一个找到的是空值,并不是第一个undefined
console.log("array.includes(false)",array.includes(false));
// false 因为这里是全等判断,并不会隐试类型转换
console.log("array.includes(0)",array.includes(0));
// true 可以获取到,因为js中0、 -0、 +0 三个值是全等的
console.log("array.includes(NaN)",array.includes(NaN));
// true 虽然 NaN === NaN 是false,但是这里可以拿到
console.log("array.includes()",array.includes());
// true 当不传入查找的值时,相当于查询的值为undefined,这个时候会查找数组中是否有空值或者有undefined值
console.log("[].includes()",[].includes());
// false 如果是空数组进行空值查找直接返回false
console.log("array.includes(1, 4)",array.includes(1, 4));
// false 这里给定了从指定位置开始查找1,所以返回false
console.log("array.includes(null, -100)",array.includes(null, -100));
// true 这里给定的是一个负值,并且 length + -100小于0,所以从0开始查找
console.log("Array.prototype.includes.call('abc', 'b')",Array.prototype.includes.call('abc', 'b'));
// true 可以通过call方法在其他非数组的类型中查找某个值
console.log("array.includes(1, true)",array.includes(1, true));
// false 这里会把true转换成1
console.log("array.includes(1, false)",array.includes(1, false));
// true 这里会把true转换成0
兼容写法
if(!Array.prototype.includes){
Array.prototype.includes = function(){
let arr = this;
let len = arr.length;
// 如果当前数组为空,直接返回false
if(!len){
return false;
}
//先把fromIndex 转换成数值类型
let fromIndex = Number(arguments[1]);
// 然后判断是否为可以转换成数字,如果不能直接赋值0
fromIndex = isNaN(fromIndex) ? 0 : fromIndex;
// 如果传入的开始位置大于数组长度,直接返回false
if(fromIndex > len){
return false;
}
// 当传入的是负数
if(fromIndex < 0){
// 通过数组长度加fromIndex然后和0去最大值
fromIndex = Math.max(0, len + fromIndex);
}
let i = fromIndex;
let findVal = arguments[0];
// 开始循环
while(i<len){
// 判断如果当前项和要查找的值全等,返回true ,如果是NaN值,还要进行isNaN判断
if(arr[i] === findVal || isNaN(arr[i]) && isNaN(findVal)){
return true;
}
i++;
}
// 都没找到返回false
return false;
}
}
array.indexOf()
从数组的左边开始向右进行查找,查找某个值第一次出现的位置,如果存在则返回这个值在数组中第一次出现的索引号,如果不存在则返回
-1
IE9 以上浏览器支出
array.indexOf(findVal, fromIndex)
参数
findVal
:表示要查找的值,这里的查找比较是通过===全等的形式进行比较fromIndex
:非必填,表示从数组的哪个位置开始查找,如果给定的值大于数组的length
那么直接返回-1
,如果给定的值为负数那么先进行length + fromIndex
如果计算出来的结果还是负数,那么就从第一个开始查找,也可以理解成从后往前数的位置。
示例
let array = [1, 2, 3, 4, , 5, undefined, null, NaN, true, -0];
console.log("array.indexOf(undefined)",array.indexOf(undefined));
// 6 indexOf方法并不会把数组中的空值转换成undefined,所以他会找到第一个真正的undefined出现的位置
console.log("array.indexOf(false)",array.indexOf(false));
// -1 因为这里是全等判断,并不会隐试类型转换
console.log("array.indexOf(0)",array.indexOf(0));
// 10 可以获取到,因为js中0、 -0、 +0 三个值是全等的
console.log("array.indexOf(NaN)",array.indexOf(NaN));
// -1 indexOf并不能查找NaN 因为NaN !== NaN
console.log("array.indexOf()",array.indexOf());
// 6 当不传入查找的值时,相当于查询的值为undefined
console.log("[].indexOf()",[].indexOf());
// -1 如果是空数组进行空值查找直接返回-1
console.log("array.indexOf(1, 4)",array.indexOf(1, 4));
// -1 这里给定了从指定位置开始查找1,所以返回false
console.log("array.indexOf(null, -100)",array.indexOf(null, -100));
// 7 这里给定的是一个负值,并且 length + -100小于0,所以从0开始查找
console.log("array.indexOf(1, true)",array.indexOf(1, true));
// -1 这里会把true转换成1
console.log("array.indexOf(1, false)",array.indexOf(1, false));
// 0 这里会把true转换成0
兼容写法
if(!Array.prototype.indexOf){
Array.prototype.indexOf = function(){
let arr = this;
let len = arr.length;
if(!len){
return -1;
}
let fromIndex = Number(arguments[1]);
fromIndex = isNaN(fromIndex) ? 0 : fromIndex;
if(fromIndex < 0){
fromIndex = Math.max(0, len + fromIndex);
}
if(fromIndex > len){
return false;
}
let i = fromIndex;
let findVal = arguments[0];
while(i<len){
if(i in arr){
if(arr[i] === findVal){
return i;
}
}
i++;
}
return -1;
}
}
array.join()
将数组中的所有项连接成为一个字符串,并且以给定的参数作为两项之间的连接符,如果不传拼接参数默认为
,
,如果数组的length不大于1,直接返回第一项
array.join(separator)
参数
separator
:非必填,默认,
把数组转换成字符串时数组项之间的连接符
示例
let array = [1, , '5', undefined, null, NaN, true, false, 0, -0, function(){let x = 10;}, {a:20}, [3], [50,[40, [90, 80, [100, 200]]]]];
console.log(array.join());
// 1,,5,,,NaN,true,false,0,0,function(){let x = 10;},[object Object],3,50,40,90,80,100,200
// 输入数组项为undefined、null的话,直接转换成空字符串
// 为没项值调用toString()方法进行类型转换,然后把转换后的值和给定的参数进行拼接
console.log(array.join('-'));
// 1--5---NaN-true-false-0-0-function(){let x = 10;}-[object Object]-3-50,40,90,80,100,200
console.log(array.join(''));
// 15NaNtruefalse00function(){let x = 10;}[object Object]350,40,90,80,100,200
// 当传入的参数是空字符串,不适用任何连接符,直接连接每一项
array.keys()
获取返回数组中的索引值组成的数组 Iterator对象
语法
array.keys()
array.lastIndexOf()
从数组的右边开始向左进行查找,查找某个值在数组中最后一次出现的位置,如果找到返回数组的下标索引号,如果没有找到返回
-1
, IE9及以上浏览器支持
语法
array.lastIndexOf(findVal, fromIndex)
参数
findVal
: 要查找的值fromIndex
:非必填,从数组的哪个位置开始查找
示例
let array = ['a', 'b', 'c', 'd', 'e', 'a', 'c', 'b', 'd'];
console.log(array.lastIndexOf('b'));
// 7
console.log(array.lastIndexOf('b', -3));
//1
array.map()
遍历数组中的每一项,并且为每一项调用提供的回调函数,此方法会创建一些新数组,新数组中的项为每一次遍历数组项的回调函数的返回值
语法
array.map(callBack(currentVal, index, array){}, thisAge)
参数
callBack
循环数组后为每项执行的回调函数currentVal
表示循环遍历时的当前项index
表示当前项的索引值array
表示当前的数组
thisAge
表示改变回调函数里的this指向
示例
let array = [10, 12, 20, 40, , 80, undefined, null, NaN];
let newArray_1 = array.map(function(curVal, curIndex, array){
// map 循环的时候会跳过空项
return curVal + 5;
});
console.log(newArray_1);
// (9) [15, 17, 25, 45, 空白, 85, NaN, 5, NaN]
var a = Array.prototype.map.call("This is Array", function(x) {
return x.charCodeAt(0);
});
console.log(a);
// (13) [84, 104, 105, 115, 32, 105, 115, 32, 65, 114, 114, 97, 121]
// 通过call方法让数组可以调用map方法,并且返回每一个字符的ASCII值
array.pop()
从数组的末尾删除数组最后一项,并且返回被删除的该项的值,此方法会改变原数组
语法
array.pop()
示例
let array = [10, 12, 20, 40, , 80, undefined, null, NaN];
let lastVal_1 = array.pop();
console.log(lastVal_1);
// NaN
console.log(array);
//(8) [10, 12, 20, 40, 空白, 80, undefined, null]
let array_1 = [];
console.log(array_1.pop());
// undefined
console.log(array_1);
// []
let array_2 = [,,]
console.log(array_2.pop());
// undefined
console.log(array_2);
// [空白]
// NaN
array.push()
向数组的末尾添加一个或多个项,并且返回数组改变后的
length
值,此方法会改变原素组
语法
array.push(element,...,elementN)
参数
elementN
:被添加到数组末尾的元素,多个元素之间用逗号分隔
示例
let array = [10, 15, 30];
let len_1 = array.push('a', 'b');
console.log(len_1);
// 5
console.log(array);
//(5) [10, 15, 30, 'a', 'b']
let array_2 = ['a', 'b', 'c'];
let array_3 = [1, 2, 3];
// 通过使用apply的方式可以展开数组,然后调用push方法合并数组
let len_2 = Array.prototype.push.apply(array_2, array_3);
console.log(array_2);
// (6) ['a', 'b', 'c', 1, 2, 3]
console.log(array_3);
// (3) [1, 2, 3]
console.log(len_2);
// 6
let obj_1 = {
length: 1,
item_1: { a: 10 }
};
let len_3 = Array.prototype.push.call(obj_1, {item_2: [1, 2]});
console.log(len_3);
// 2
console.log(obj_1);
// 1: {item_2: Array(2)}
// item_1: {a: 10}
// length: 2
// 通过给具有length的对象调用push方法,会改变length的值,同时已下标的像是把项推送到对象中
array.reduce()
reduce
中文意思:“减少,把…分解” 循环遍历数组,并且为数组中的每一项执行一下回调函数,并且将所有项回调函数处理结果返回
语法
arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])
参数
callBack
:循环迭代数组提供的回调方法accumulator
:中文翻译为累加器
,当遍历数组第一个值得时候,该值为initialValue
,如果没有提供该值,那么它会取数组的第一个值。从遍历第二次开始该值的取值为上次上一次callBack
的返回值。currentValue
:遍历数组时正在处理的当前值,如果是第一次调用,并且没有提供initialValue
参数,那么它就取第二个值作为当前值,如果提供了initialValue
参数,那么它取第一个值。index
:当前处理数组项的索引下标值,也就是currentValue
的下标值array
:当前处理的函数
initialValue
: 中文翻译为最初的值
,也就是第一次遍历的时候accumulator
的值
示例
let array_1 = [2, 5, 8, 10];
let getSum_1 = array_1.reduce(function(prv, next, index, array) {
// console.log(index);
return prv + next;
});
// 上边循环输出的键值
// 1 2 3
// console.log(getSum_1);
// 25
let getSum_1_1 = array_1.reduce(function(prv, next, index, array){
// console.log(index);
return prv + next;
}, 0);
// 上边循环输出的键值
// 0 1 2 3
// console.log(getSum_1_1);
// 25
// 两次计算的结果是相同的,只是循环遍历的次数不一样,如果不提供第二个参数的话,第一次的回调函数会自动拿数组的第一个和第二个值
let array_2 = [10];
let getSum_2 = array_2.reduce(function(prv, next){
console.log(prv);
console.log(next);
return prv + next;
});
// 这里的回调函数没有执行,reduce直接返回了函数的第一个值,当数组只有一项的时候,并且没有提供第二个参数,reduce直接返回第一项的值
console.log(getSum_2);
// 10
let getSum_2_1 = array_2.reduce(function(prv, next){
console.log(prv);
console.log(next);
return prv + next;
}, 0);
// 0 10 当数组只有一项的时候,如果提供了第二个参数,那么会进入
console.log(getSum_2_1);
// 10
兼容写法
if(Array.prototype.reduce){
Array.prototype.reduce = function(callBack, initialVal){
let array = this;
if(array === null){
throw new TypeError('Array.prototype.reduce called on null or undefined');
}
if(typeof(callBack) !== 'function'){
throw new TypeError( callback +' is not a function');
}
let len = array.length;
if(len === 1 && initialVal === undefined){
return array[0];
}
let i;
let prv, next;
if(initialVal != undefined){
i = 0;
prv = initialVal;
next = array[0];
}else{
i = 1;
prv = array[0];
next = array[1];
}
while(i < len){
prv = callBack(prv, next, i, array);
next = array[++i];
}
return prv;
}
}
array.reduceRight()
reduceRight
和reduce
函数类似,它是把函数从右向左遍历并且为数组中的每一项执行一下回调函数,并且将所有项回调函数处理结果返回
语法
arr.reduceRight(callback(accumulator, currentValue[, index[, array]])[, initialValue])
参数
callBack
:循环迭代数组提供的回调方法accumulator
:中文翻译为累加器
,当遍历数组第一个值得时候,该值为initialValue
,如果没有提供该值,那么它会取数组的最后一个值。从遍历第二次开始该值的取值为上次上一次callBack
的返回值。currentValue
:遍历数组时正在处理的当前值,如果是第一次调用,并且没有提供initialValue
参数,那么它就取倒数第二个值作为当前值,如果提供了initialValue
参数,那么它取最后一个值。index
:当前处理数组项的索引下标值,也就是currentValue
的下标值array
:当前处理的函数
initialValue
: 中文翻译为最初的值
,也就是第一次遍历的时候accumulator
的值
示例
let array = ['a', 'b', 'c', 'd', 'e'];
let getNewArray = array.reduceRight((prv, next)=>{
prv.push(next);
return prv;
}, []);
console.log(getNewArray);
// (5) ['e', 'd', 'c', 'b', 'a']
array.reverse()
颠倒数组中所有项的位置,并且返回颠倒后的数组,该方法会改变原数组
语法
array.reverse();
示例
let array = ['a', 'b', 'c', 'd', 'e'];
let getArray = array.reverse();
console.log(getArray);
console.log(array);
// (5) ['e', 'd', 'c', 'b', 'a']
// (5) ['e', 'd', 'c', 'b', 'a']
let obj = {0: 10, 1: 20, 2: 30, length: 3};
let getObj = Array.prototype.reverse.call(obj);
console.log(obj);
// {0: 30, 1: 20, 2: 10, length: 3}
console.log(getObj);
// {0: 30, 1: 20, 2: 10, length: 3}
let obj_2 = {a: 10, b: 20, c: 30, length: 3};
let getObj_2 = Array.prototype.reverse.call(obj_2);
console.log(getObj_2);
// {a: 10, b: 20, c: 30, length: 3}
// 只有当对象的键值是以0开头的连续下标才能生效
array.shift()
删除数组中的第一个元素并返回被删除的项,如果是空数组那么返回undefined,此方法会改变原数组
语法
array.shift()
示例
let array = ['a', 'b', 'c', 'd', 'e'];
console.log(array.shift());
// 4
console.log(array);
// (4) ['b', 'c', 'd', 'e']
array.slice()
此方法回提取一个数组中某段的值,并且返回一个新数组,他会从给定的参数
begin
下标开始提取到end
下标结束,但是不包括end下标的值
语法
array.slice(begin, end);
参数
begin
:可选值,要提取的开始下标,如果下标大于数组的length那么返回空数组,如果下标小于0那么就从数组的末尾向左数的倒数第几位,如果不提供默认从第0个下标开始截取end
:可选值,要截取的结束下标,如果值大于length那么直接截取到数组末尾值,如果下标小于0那么从数组的末尾向左数的倒数第几位,如果不提供默认截取数组末尾
示例
let array = ['a', 'b', 'c', 'd', 'e'];
let getArr_1 = array.slice();
console.log(getArr_1);
// (5) ['a', 'b', 'c', 'd', 'e']
let getArr_2 = array.slice(2);
console.log(getArr_2);
// (3) ['c', 'd', 'e']
let getArr_3 = array.slice(2, 3);
console.log(getArr_3);
// ['c']
let getArr_4 = array.slice(-4, -1);
console.log(getArr_4);
// (3) ['b', 'c', 'd']
let getArr_5 = array.slice(8);
console.log(getArr_5);
// []
// 把类数组转换成数组
let spanLinkArr = document.getElementsByTagName('span');
let spanArr = Array.prototype.slice.call(spanLinkArr);
console.log(spanLinkArr);
// HTMLCollection(10) [span, span, span, span, span, span, span, span, span, span]
console.log(spanArr);
// (10) [span, span, span, span, span, span, span, span, span, span]
array.some()
通过遍历数组中的每一项,然后为每一项执行一个回调函数,在函数中进行数组项的检测,如果回调函数中有一个返回
true
,那么some就返回true
,否则返回false
语法
array.some(callBack(currentVal, index, array), thisAge);
参数
callBack
:循环为数组没项执行的回调函数currentVal
:循环遍历的当前项index
:当前项的索引值array
:当前遍历的数组
thisAge
:可选值,改变回调函数的this执行
示例
let array = [10, 4, 20, 5, 8, 38, 40, 20];
let test_1 = array.some(function(val, index, arr){
return val > 20;
});
console.log(test_1);
// true
let test_2 = array.some(function(val, index, arr){
return val > 120;
});
console.log(test_2);
// false
let array_2 = ['a', 'b', 'c', 'd', 'e', 'f'];
function haveVal(arr, val){
return arr.some((v, i)=>{
return v === val;
});
}
console.log(haveVal(array_2, 'c'));
// true
console.log(haveVal(array_2, 'g'));
// false
array.sort()
给数组进行排序,并且返回排序后的数组,该方法会改变元素组,默认情况下排序规则是把每一项转换成字符串,然后按照字符串的Unicode编码顺序进行排序,我们也可以提供一个回调函数进行改变排序规则
语法
array.sort(fun(firstVal, secondVal))
参数
fun
用来指定某种排序的方法,该方法提供两个参数,通过此方法的返回值进行排序
-firstVal
:进行比较的第一个值secondVal
:进行比较的第二个值
示例
let numArr = [4, 2, 50, 5, 11, 10, 3, 0, 20, 25, 6];
let firstSort = numArr.sort();
console.log(firstSort);
// 当不提供排序回调函数的时候按照数组中的项的Unicode码进行排序
//(11) [0, 10, 11, 2, 20, 25, 3, 4, 5, 50, 6]
let secondSort = numArr.sort((a, b)=>{
return a - b;
});
console.log(secondSort);
// (11) [0, 2, 3, 4, 5, 6, 10, 11, 20, 25, 50]
let thirdSort = numArr.sort((a, b)=>{
return b - a;
});
console.log(thirdSort);
// (11) [50, 25, 20, 11, 10, 6, 5, 4, 3, 2, 0]
let fourSort = [4, 2, 50, 5, 11, 10, 3, 0, 20, 25, 6].sort((a, b)=>{
return 0;
});
console.log(fourSort);
// (11) [4, 2, 50, 5, 11, 10, 3, 0, 20, 25, 6]
array.splice()
删除数组中的某些元素同时可以向数组中指定的位置添加一个或者多个元素,此方法返回一个被删除的元素组成的数组,如果没有删除元素的则返回空数组,此方法会改变原来的数组
语法
array.splice(startIndex[, deleteCount [,item1,...,itemN]])
参数
startIndex
:表示从哪个位置开始修改或删除元素,如果为负数表示从数组的末尾开始向左数第一个元素开始,如果此值大于数组的length,那么就从数组开始添加元素deleteCount
:表示删除数组项的个数,如果此值大于startIndex
到数组末尾的项的总和那么将删除开始位置往后的所有元素,如果此值为0或者为负数,不执行删除操作item1,...,itemN
:表示要添加的一个或多个数组元素,多个元素之间用逗号分隔
示例
let array = [1, 2, 3, 4, 5, 6, 7, 8];
let array_1 = array.concat([]);
console.log(array_1.splice(3));
// 从数组的第三个位置开始删除所有元素
// (5) [4, 5, 6, 7, 8]
console.log(array_1);
// (3) [1, 2, 3]
let array_2 = array.concat([]);
console.log(array_2.splice(3, 1));
// [4]
console.log(array_2);
// (7) [1, 2, 3, 5, 6, 7, 8]
let array_3 = array.concat([]);
console.log(array_3.splice(3, 0));
// []
console.log(array_3);
// (8) [1, 2, 3, 4, 5, 6, 7, 8]
let array_4 = array.concat([]);
console.log(array_4.splice(5, 2, 'a', 'b', 'c'));
// (2) [6, 7]
console.log(array_4);
// (9) [1, 2, 3, 4, 5, 'a', 'b', 'c', 8]
let array_5 = array.concat([]);
console.log(array_5.splice(-3, 4, 'a'));
// (3) [6, 7, 8]
console.log(array_5);
// (6) [1, 2, 3, 4, 5, 'a']
array.toLocaleString()
将数组中的元素使用各自的类型中的toLocaleString方法进行转换,然后把每个项转换后的值以逗号的形式进行分隔并且返回改字符串
语法
array.toLocaleString([locales[, options]])
参数
locales
:可选值,带有BCP 47语言标记的字符串或字符串数组options
:可选值,一个可配置属性的对象
示例
let array = [1, 'a', new Date(), [1, 2], {a: 10, b: 20}, function(){console.log(888)}, NaN, undefined, false]
console.log(array.toLocaleString('en', { timeZone: 'UTC' }));
// 1,a,11/24/2021, 3:11:54 PM,1,2,[object Object],function(){console.log(888)},NaN,,false
var prices = ['¥7', 500, 8123, 12];
console.log(prices.toLocaleString('ja-JP', { style: 'currency', currency: 'JPY' }));
//¥7,¥500,¥8,123,¥12
array.toString()
该方法会返回一个数组元素组成的字符串
语法
array.toString();
示例
let array = [1, 'a', new Date(), [1, 2], {a: 10, b: 20}, function(){console.log(888)}, NaN, undefined, false];
console.log(array.toString());
// 1,a,Wed Nov 24 2021 23:21:48 GMT+0800 (中国标准时间),1,2,[object Object],function(){console.log(888)},NaN,,false
array.unshift()
将一个或多个值添加到数组的开头位置, 此方法会改变元素组, 并且返回更改后的数组长度值
语法
array.unshift(item1, ..., itemN);
示例
let array = [10, 20, 40];
let length = array.unshift('a', 'b');
console.log(length);
// 5
console.log(array);
// (5) ['a', 'b', 10, 20, 40]
array.values()
此方法会返回一个Array Iterator 对象,该方法包含了每个数组的值,并且可以通过多次调用next()方法获取每个值
var array = ['a', 'b', 'c', 'd', 'e'];
var iterator = array.values();
console.log(iterator);
// Array Iterator {}
console.log(iterator.next());
// 通过调用iterator的next方法来获取每一项
// {value: 'a', done: false}
// 也可以通过for of方法遍历出所有项
for (let letter of iterator) {
console.log(letter);
}
// "b" "c" "d"
参考网站
- https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array