javascript 数组: 单一变量存储多个值
数组每个值叫做一个元素,而每个元素在数组中有一个位置,以数字表示,称为索引。
- 数组是值的有序集合
- 固定长度
- 可以存放不同的数据结构
- 一段线性分配的内存.
常用方法
属性 | 名称 | 说明 |
---|---|---|
length | 长度方法 | 长度方法 |
名称 | 说明 |
---|---|
concat() | 连接两个或多个数组,并返回已连接数组的副本。 |
copyWithin | 将数组中的数组元素复制到指定位置或从指定位置复制。 |
entries | 返回键/值对数组迭代对象。 |
every | 检查数组中的每个元素是否通过测试。 |
fill | 用静态值填充数组中的元素。 |
filter | 使用数组中通过测试的每个元素创建新数组。 |
find | 返回数组中第一个通过测试的元素的值。 |
findIndex | 返回数组中通过测试的第一个元素的索引。 |
forEach | 为每个数组元素调用函数。 |
from | 从对象创建数组。 |
includes | 检查数组是否包含指定的元素。 |
indexOf | 在数组中搜索元素并返回其位置。 |
isArray | 检查对象是否为数组。 |
join | 将数组的所有元素连接成一个字符串。 |
keys | 返回 Array Iteration 对象,包含原始数组的键. |
lastIndexOf | 在数组中搜索元素,从末尾开始,并返回其位置。 |
map | 使用为每个数组元素调用函数的结果创建新数组。 |
pop | 删除数组的最后一个元素,并返回该元素。 |
push | 将新元素添加到数组的末尾,并返回新的长度。 |
reduce | 将数组的值减为单个值(从左到右)。 |
reduceRight | 将数组的值减为单个值(从右到左)。 |
reverse | 反转数组中元素的顺序。 |
shift | 删除数组的第一个元素,并返回该元素。 |
slice | 选择数组的一部分,并返回新数组。 |
some | 检查数组中的任何元素是否通过测试。 |
sort | 对数组的元素进行排序。 |
splice | 从数组中添加/删除元素。 |
toString | 将数组转换为字符串,并返回结果。 |
unshift | 将新元素添加到数组的开头,并返回新的长度。 |
详解
slice 函数
截取数组中的几个元素 组成新的数组
- slice(start,end)表示从下标start开始到下标end(不包括end)进行截取,得到的是一个新数组,不改变原数组。
- 当start为负值时表示从倒数第几个元素开始往后截取
- 不填end的话就表示从倒数第几个元素开始截取,一直截取到数组末尾元素。
// 简单复制,浅拷贝
var _array = [1,2,3,4,5]
var copyArray = _array.slice();
// 获取从 N 开始的子数组
// 希望弹出数组的第一个元素并使用它,返回剩余的数组,但希望在不修改原始数组的情况下执行此操作。
function useone (arr) {
const usedItem = arr[0]
return arr.slice(1)
}
// 获取从末尾 N 开始的子数组,负索引使删除任意数量的元素变得简单
const sliceArr = _array.slice(-3)
console.log('sliceArr ',sliceArr) //[3,4,5]
// 获取数组的前n个
const first4 = _array.slice(0, 4) // [1,2,3,4]
// 获取数组中某段子数组
function getSegement(arr, begin, length) {
return arr.slice(begin, begin + length);
}
console.log(getSegement(_array,1,3)) // [2,3,4]
// 类似数组的对象转换
Array.prototype.slice.call(arguments)
// 修改数组中的特定索引
// slice在函数上下文中一个强大而常见的用法是替换数组中特定项的值。从本质上讲,这很简单,只需要分配新值,但是在函数世界中,不能修改原始数组。相反,可以将slice与扩展运算符一起使用,以返回一个相同但对于要更新的索引的新数组:
function replaceIdx(arr,index,newVal) {
return [
...arr.slice(0,index),
newVal,
...arr.slice(index+1)
]
}
// 偏函数应用
var partial = function() {
const fn = arguments[0];
const args = Array.prototype.slice.call(arguments, 1);
// Return a function that calls fn
return function() {
var remainingArgs = Array.prototype.slice.call(arguments);
return fn.apply(this, args.concat(remainingArgs));
}
}
// 将任意长度多余的参数强制转换为数组
function myFunc(a, b) {
const extraArgs = Array.prototype.slice.call(arguments, 2);
}
myFunc(1, 2, 3, 4, 5, 6, 7, 8) // 得到a == 1,b === 2,extraArgs=== [3,4,5,6,7,8]
splice 函数
splice()方法有三个参数,分别表示从哪个下标开始,删几个元素。可以实现增加,删除,替换数组元素的功能。arr.splice(-5,5)表示从倒数第五个元素开始,删五个元素。巧妙的是该方法的返回值是删除的元素集合。同时该方法改变了原数组。原数组变成了除了删除的元素剩下的元素集合。
var numbers = [1,2,3,'hello','javascript',33,'world', {"name":"wxh","age":33}];
// 复制数组
var _array = [];
console.log(numbers.splice(0,2,'a','b','c')) // [ 1, 2 ]
console.log(numbers) // [ 'a','b','c', 3,'hello','javascript',33,'world',{ name: 'wxh', age: 33 } ]
forEach 函数
//标准
forEach(callback[,thisArg])
//简单示例
Array.forEach(function(item, index, array){
//回调函数内容
}, args);
// 扩展
if (!Array.prototype.forEach) {
Array.prototype.forEach = function (callback, thisArg) {
for (var i = 0; i < this.length; i++) {
//当thisArg为undefined时,JS引擎会将window作为其调用者
if (this[i])
callback.call(thisArg, this[i], i, this);
}
}
}
filter 函数
3个参数同forEach,args也同forEach,唯一不同的是,函数有回调函数里有return返回值。
- 简单来说,该方法返回值是一个数组。
- 初始时,这个数组是空数组,该方法会通过回调函数遍历整个数组(指Array这个),
- 假如当前的元素返回值为true(或者可以隐式转换为true的,比如一个长度大于0的字符串),
- 那么会将当前元素添加到被返回的数组中。
例如:[1, 2, 3],
回调函数的return是item > 1,
当第一个元素1时,1>1为false,因此不会添加到返回的数组中,
而2和3 >1显然是true,因此会被添加到数组中。最终,返回值是[2,3]。
//标准
filter(callback[,thisArg])
//简单示例
Array.filter(function(item, index, array){
//回调函数内容
}, args);
// 扩展
if (!Array.prototype.filter) {
Array.prototype.filter = function (callback, thisArg) {
var temp = [];
for (var i = 0; i < this.length; i++) {
if (this[i]) {
if (callback.call(thisArg, this[i], i, this)) {
//如果callback返回true,则该元素符合过滤条件,将元素压入temp中
temp.push(this[i]);
}
}
}
return temp;
}
}
map 函数
3个参数同forEach,args也同forEach,唯一不同的是,函数有回调函数里有return返回值。
简单来说,该方法的返回值也是一个数组(类filter);
- 和filter的区别在于,filter是将原数组元素,选择性加入到新数组中。
- map是将原数组的每个元素,进行处理后,放到新数组中。
例如:[1,2,3]作为原数组,map回调函数内的代码为:
return item + 10;
那么就相当于将1+10放到数组中,然后将2+10放到数组中,再将3+10放到数组中。
结果为:[11, 12, 13]
当然,也可以写更复杂的逻辑,比如if(item>3)时+10,然后else if(item>2)时+5,否则else -10
那么结果就是[-9, 7, 13]
//标准
map(callback[,thisArg])
//简单示例
Array.map(function(item, index, array){
//回调函数内容
}, args);
// 扩展
if (!Array.prototype.map) {
Array.prototype.map = function (callback, thisArg) {
var temp = [];
for (var i = 0; i < this.length; i++) {
if (this[i]) {
var newItem = callback.call(thisArg, this[i], i, this);
temp[i] = newItem//将callback返回的新元素压入temp中
}
}
return temp;
}
}
reduce 函数
首先看回调函数,他有四个参数,
item是当前元素,别的地方写的是currentValue表示当前值,为了方便理解,我这里写item和上面统一风格
index是当前元素的索引;
Array是整个数组(可以通过这个修改源数组);
上面3个都很好理解。
第一个参数previousValue是核心。他表示上一次执行回调函数时的返回值。
例如,有数组[1, 2, 3, 4]
当我遍历到第二个元素时,回调函数的previousValue的值是1,item的值为2,
return我写为:return previousValue + item
那么当遍历到第三个元素时,回调函数的previousValue的值则为3(因为1+2),item的值为3
当遍历到第四个元素时,previous的值则为6(因为3+3),
最终reduce的返回值为10(因为6+4)
那么问题来了,为什么没提到遍历第一个元素?
原因是,当reduce没有第二个参数时,遍历从数组的第二个元素开始,
第一次执行回调函数的previousValue的值是数组第一个元素的值
当reduce存在第二个参数时(哪怕是null或者undefined),遍历都将从第一个元素开始;
第一次执行回调函数时(遍历第一个元素),previousValue的值是第二个参数的值,而item是第一个元素的值
所以在使用的时候需要注意,如果需要执行和数组元素个数一样次数的回调函数,那么必须设置reduce的第二个参数;
如果不设置,那么回到函数次数执行的次数,将比数组元素个数少1。
//标准
reduce(callback[,initialValue])
//简单示例
arr.reduce(function (previousValue, item, index, Array) {
return xxx; //xxx表示省略
});
// 扩展
if (!Array.prototype.reduce) {
Array.prototype.reduce = function (callback, initialValue) {
var previousValue = initialValue || this[0];//如果不指定intialValue,则默认为数组的第一个元素
//如果不指定initialValue(即第二个参数),i从1(第二个元素)开始遍历,否则就从0(第一个元素)开始遍历
for (var i = initialValue ? 0 : 1; i < this.length; i++) {
//previousValue 累加每一次返回的结果
if (this[i])
previousValue = callback(previousValue, this[i], i, this.toString());
}
return previousValue;
}
}
reduceRight 函数
//标准
reduceRight(callback[,initialValue])
//简单示例
arr.reduceRight(function (previousValue, item, index, Array) {
return xxx; //xxx表示省略
});
// 扩展
if (!Array.prototype.reduceRight) {
Array.prototype.reduceRight = function (callback, initialValue) {
var previousValue = initialValue || this[this.length - 1];//如果不指定intialValue,则默认为数组的第一个元素
//如果不指定initialValue(即第二个参数),i从1(第二个元素)开始遍历,否则就从0(第一个元素)开始遍历
for (var i = (initialValue ? this.length - 1 : this.length - 2); i > -1; i--) {
//previousValue 累加每一次返回的结果
if (this[i])
previousValue = callback(previousValue, this[i], i, this);
}
return previousValue;
}
}
every 函数
返回值是true或者false
初始情况下是true;
然后遍历数组,有一个不满足,则为false,并且终止遍历过程。
回调函数的this依然默认指向window,或者是every的第二个参数。
空数组的every返回结果是true。
//标准
every(callback, thisArg);
//简单示例
arr.every(function(item, index, array){
return item > xx;
});
if (!Array.prototype.every) {
Array.prototype.every = function (callback, thisArg) {
var result = true;
for (var i = 0; i < this.length; i++) {
if (this[i]) {
if (!callback.call(thisArg ? thisArg : window, this[i], i, this)) {
result = false;
break;
}
}
}
return result; //所有元素都符合条件,返回true
}
}
indexOf 函数
用于查找第一个参数是否在数组中;
如果不在,返回-1;
如果在,返回在数组中遇见的第一个的下标;
例如:[1,2,3,2].indexOf(2)的返回值是1,虽然第二个和第四个元素都是,但是先遇见第二个,而第二个的下标是1
如果indexOf有第二个参数,那么从数组中第二个参数所指向的下标位置开始往后找;
例如:[1,2,3,2].indexOf(2,2)的返回值是3,因为开始下标是2(即第三个元素3),因此从第三个开始,遇见的第一个2的下标是2;
判断时含第二个参数所指向的数组元素
//标准
arr.indexOf(searchElement, fromIndex);
//简单示例
[1,2,3].indexOf(2); //1(数组的第二个元素)
[1,2,3].indexOf(4); //-1(未找到,注意,-1不是false,隐式转换后他的值为true)
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function (searchElement, fromIndex) {
var result = -1;
for (var i = fromIndex ? fromIndex : 0; i < this.length; i++) {
if (this[i]) {
if (searchElement === this[i]) {
result = i;
break;
}
}
}
return result; //所有元素都符合条件,返回true
}
}
lastIndexOf 函数
//标准
arr.lastIndexOf(searchElement, fromIndex);
//简单示例
[1,2,1].lastIndexOf(1); //2
[1,2,1].lastIndexOf(1, 1); //0
if (!Array.prototype.lastIndexOf) {
Array.prototype.lastIndexOf = function (searchElement, fromIndex) {
var result = -1;
for (var i = (fromIndex ? fromIndex : this.length - 1); i > -1; i--) {
if (this[i]) {
if (searchElement === this[i]) {
result = i;
break;
}
}
}
return result; //所有元素都符合条件,返回true
}
}
from 函数
Array.from() 从类数组对象或者可迭代对象中创建一个新的数组实例。
console.log(Array.from([1,2,3],x=>x*x)); // 2,4,9
Array.isArray() 用来判断某个变量是否是一个数组对象。
console.log(Array.isArray(Array.from([1,2,3]))); // true
Array.of() 根据一组参数来创建新的数组实例,支持任意的参数数量和类型。
console.log(Array.of(1, 2, 3));// [1,2,3]
concat 函数
连接两个或更多的数组,并返回结果
var arr = [ 1, 2, 3 ];
var arr2= arr.concat("4", "5", "6"); //["1", "2", "3", "4", "5", "6"];
join 函数
把数组的所有元素放入一个字符串并通过指定的分隔符进行分隔
arr.join("+"); //"1+2+3";
reverse 函数
反转数组中元素的顺序。
arr.reverse();
console.log(arr); // [3, 2, 1];
sort 函数
数组排序 按照字符串的方式来排序。
toString 函数
把数组转换为字符串,并返回结果
find 函数
返回传入一个测试条件,符合条件的数组第一个元素,当数组中的元素在测试条件时返回true时, find() 返回符合条件的元素,之后的值不会再调用执行函数。如果没有符合条件的元素返回 undefined
const pets = [
{ type: 'Dog', name: 'Max'},
{ type: 'Cat', name: 'Karl'},
{ type: 'Dog', name: 'Tommy'},
];
var pet = pets.find(pet => pet.type ==='Dog' && pet.name === 'Tommy');
console.log(pet); // { type: 'Dog', name: 'Tommy' }
some 函数
用于检测数组中的元素是否满足指定条件,如果有一个元素满足条件,则表达式返回true, 剩余的元素不会再执行检测,如果没有满足条件的元素,则返回false。
let arr = [1, 2, 3, 4, 5]
console.log(arr.some(item => item === 2)); // true
// ES5循环实现 some 方法
const selfSome = function (fn, context) {
let arr = Array.prototype.slice.call(this) // 复制数组原型对象
// 空数组直接返回 false,数组的 every 方法则相反返回 true
if(!arr.length) return false
for (let i = 0; i < arr.length; i++) {
if(!arr.hasOwnProperty(i)) continue;
let res = fn.call(context,arr[i],i,this)
if(res)return true
}
return false
}
// 挂载
Array.prototype.selfSome ||(Object.defineProperty(Array.prototype, 'selfSome', {
value: selfSome,
enumerable: false,
configurable: true,
writable: true
}))
console.log(arr.selfSome(item => item === 2)) // true
数组与字符串转换
var arr = ['wxh','cjk','dbt','cjk']
console.log(arr.join(",")) // 以 逗号 进行分割
Array.from(new Set(arr)) // ['wxh','cjk','dbt'] // 数组去重
var str = "wxh,cjk,dbt"
console.log(str.split(","))
console.log(Array.from(str)) // ['w', 'x', 'h', ',',....]
数组与对象转换
let arrayLike = {
'0': 'wxh',
'1': 'cjk',
'2': 'dbt',
length: 3
};
// ES5 的写法
var arr1 = [].slice.call(arrayLike); // ['wxh', 'cjk', 'dbt']
// ES6 的写法
let arr2 = Array.from(arrayLike); // ['wxh', 'cjk', 'dbt']
// NodeList 对象
let arr3 = document.querySelectorAll('p');
Array.from(arr3).forEach(function (item) {
console.log(item);
});
// arguments 对象
function foo() {
var args = Array.from(arguments);
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。