layout: post
title: JS 中的 Array对象
tag: 前端开发
今天, 让我们和 JS的 Array对象来个了解吧...
构造函数
Array 是 JS的原生对象, 同时也是一个构造函数, 意味着你可以通过它生成新的数组. 如:
const arr = new Array(2);
然而, 我们强烈反对你这样做 !
因为 Array构造函数有一个很大的缺陷, 不同的参数会导致它的行为不一致:
参数为 空时, 返回一个空数组;
参数为 单个正整数, 返回一个定长的数组;
参数为 非正整数的数值, 会报错;
参数为 非数值(如字符串/布尔值/对象等), 返回以该参数为成员的新数组;
参数为 多个时, 返回以所有参数为成员的新数组.
我们推荐你直接使用数组字面量的形式生成新的数组.
静态方法
Array.isArray()
我们知道 typeof
运算符在遇到引用类型的时候就无能为力了. 如何解决 ?
const arr = [1, 2, 3];typeof arr; // 'object'Array.isArray(arr); // true
通过上面这段代码, 我想你已经知道方法了.
实例方法
valueOf(), toString()
valueOf
方法和toString
方法都是 Object对象的通用方法, 允许被重写. Array对象就这么做了!
const arr = [1, 2, 3]; arr.valueOf(); // [1, 2, 3], 返回数组本身arr.toString(); // '1,2,3', 返回数组的字符串形式
那些曾经让人头痛的实例方法
相信不少人都曾经吃过不少 Array实例方法的苦,
到底 有哪些方法 ?
到底 哪些方法会改变原数组 ?
到底 这些方法怎么用 ?
到底 这些方法的参数是什么 ?
到底 这些方法的返回值是什么 ?
Okay, 我们来解决它们吧 !
会改变原数组的实例方法
push(), pop(), shift(), unshift()
const arr = []; arr.push(1); // 1arr.push('a'); // 2arr.push(true, {}); // 4arr; // [1, 'a', true, {}], 原数组改变了
你看, 通过上面这段代码, 我们能看到什么 ?
push(),
作用: 在数组的末端添加一个或多个元素
参数: 要添加的元素(数值/字符串/布尔型或对象等)
返回: 添加新元素后的数组长度
有添加了, 要有删除才可以平衡嘛 ! 于是,
const arr = ['a', 'b', 'c']; arr.pop(); // 'c', 返回删除的元素 arr; // ['a', 'b'], 原数组改变了 [].pop(); // undefined
pop(),
作用: 用于删除数组的最后一个元素
参数: 空
返回: 删除的最后一个元素
末端那些事儿解决了, 如果要在头部操作呢 ?
const arr = ['a', 'b', 'c']; arr.shift(); // 'a'arr; // ['b', 'c'], 原数组改变了
shift(),
作用: 用于删除数组的第一个元素
参数: 空
返回: 删除的第一个元素
shift 有'卸载'的意思, so, 你就不会把 shift/ unshift搞混了.
const arr = ['c', 'd']; arr.unshift('a', 'b'); // 4arr; // ['a', 'b', 'c', 'd'], 原数组改变了
unshift(),
作用: 在数组的第一个位置添加元素(一个或多个)
参数: 要添加的元素
返回: 添加新元素后的数组长度
reverse(), sort(), splice()
const arr = ['a', 'b', 'c']; arr.reverse(); // ['c', 'b', 'a'] arr; // ['c', 'b', 'a'], 原数组改变了
reverse(),
作用: 逆转排列数组元素
参数: 空
返回: 逆转排列的新数组
const arr = [1, 3, 2, 4, 101, 11]; arr.sort(); // [1, 101, 11, 2, 3, 4]arr; // [1, 101, 11, 2, 3, 4], 原数组改变了
通过上面这段代码, 可以发现, sort
方法不是按照大小排序, 而是按照字典顺序排序. 通常意义上的从小到大的排序方式怎么实现呢 ? sort
方法允许我们传入一个函数作为参数, so, 在函数中你可以制定规则了.
const arr = [1, 3, 2, 4, 101, 11]; arr.sort( function(a, b) { // 参数函数本身接受两个参数, 表示进行比较的两个数组成员 return a - b; // 返回值大于0, 表示第一个成员大, 要排在第二个成员后面 } ); // [1, 2, 3, 4, 11, 101]
sort(),
作用: 对数组元素进行排序, 默认按照字典顺序
参数: 空/ 自定义排序规则的函数
返回: 排序之后的新数组
splice
方法功能很强大哦. 我们通过它的用法很容易可以看出, 如下:
arr.splice(start, conunt, [addElement1], [addElement2], ...);
参数:
start: 删除的起始位置(从0开始, 为负代表从倒数位置开始删除)
count: 要被删除的元素个数(等于0时表示不删除, 只插入)
addElement1: 可选参数, 表示要被插入数组的新元素
const arr = ['a', 'b', 'c', 'd', 'e', 'f']; arr.splice(4, 2, 1, 2); // ['e', 'f'], 返回删除的元素 arr; // ['a', 'b', 'c', 'd', '1', '2'], 原数组改变了
splice(),
作用: 删除原数组的一部分成员, 并可以再删除位置添加新的数组成员
参数: 起始位置, 删除个数, [待插入元素...]
返回: 删除的元素组成的数组
不改变原数组的实例方法
join(), concat(), slice()
const arr = [1, 2, 3, null, 4,,5]; arr.join('-'); // 1-2-3--4--5// 数组成员为undefined, null或空位时, 会被转成空字符串// 通过 `call`方法, join()也可用于字符串和类似数组的对象,如下Array.prototype.join.call('hello', '-'); // 'h-e-l-l-o'const obj = {0: 'a', 1: 'b', length: 2};Array.prototype.join.call(obj, '-'); // 'a-b'
join(),
作用: 指定参数作为分隔符, 将所有数组成员连接为一个字符串返回
参数: 不提供参数时, 默认用逗号分隔
返回: 指定分隔符分隔之后的字符串
const arr = ['hello']; arr.concat(['world'], {a: 1, b: 2}, 6, '!');// ['hello', 'world', {a:1, b: 2}, 6, '!'] arr; // ['hello'], 原数组没有改变哦
concat(),
作用: 用于多个数组的合并, 讲过新数组的成员, 添加到原数组之后
参数: 数组, 也接受其他类型的值
返回: 合并后的新数组
如果数组成员包括对象, concat
方法返回当前数组的一个浅拷贝. 我们通过一个例子来看一下'浅拷贝'是什么 ?
const obj = {a: 1};const orgArr = [obj]; // 原数组包含一个对象const newArr = orgArr.concat();// 现在我们改变原数组包含的对象 objobj.a = 2; newArr[0].a; // 2// 可以看到我们修改obj.a, 新数组也跟着改变, 因为拷贝的是引用地址, 反之亦如此
slice
方法, 用法: arr.slice(start, end);
const arr = ['a', 'b', 'c']; arr.slice(0); // ['a', 'b', 'c'] arr.slice(1); // ['b', 'c'] arr.slice(1, 2); // ['b'] arr.slice(); // ['a', 'b', 'c'], 原数组的拷贝 arr.slice(-2); // ['b', 'c'] arr.slice(-2, -1); // ['b'] arr; // ['a', 'b', 'c'], 原数组没有改变 Array.prototype.slice.call(arguments); // `slice`方法的一个重要应用, 就是类似数组的对象转为真正的数组. // `join`方法时, 也如此用过.
slice(),
作用: 用于提取目标数组的一部分
参数: 起始位置(从0开始), 终止位置(不包括该位置本身, 省略时表示一直到原数组末尾);
参数为空, 等于返回一个原数组的拷贝
参数为负, 找寻位置时按倒数查询
如果 start >= end, 返回空数组
返回: 返回提取部分组成的新数组, 原数组不变
map(), forEach(), filter(), some(), every()
function fn(elem, index, arr) { ... }; arr.map/forEach/filter/some/every(fn, [可选参数])
参数函数中参数的解释:
elem: 当前成员
index: 当前位置
arr: 数组本身
const arr = ['1', '2'];const arra = ['a', 'b', 'c']; arr.map(function(elem, index, arr) { return elem * index; // [0, 2]}); arr.map(function(elem) { return this[elem]; }, arra); // ['b', 'c']
map(),
作用: 将数组的所有成员依次传入参数函数, 把每一次的执行结果组成一个新数组返回
参数: 接受一个函数作为参数; 第二个参数可选, 用来绑定回调函数内部的
this
变量返回: 每一次执行结果组成的新数组
注意:
map
方法, 会跳过数组的空位, 不会跳过undefined
和null
forEach
方法和map
方法的异同:
相同: 用法一致, 参数是一个函数(接受三个参数), 可以接受第二参数绑定函数内部的
this
不同:
forEach
方法不返回值, 只用来操作数据结论: 若数组遍历的目的是为了得到返回值, 用
map
方法, 否则用forEach
方法注意:
forEach
方法无法中断执行, 总是会将所有成员遍历完, 如果要按条件中断遍历, 去使用for
循环
const arr = [1, 2, 3];const out = []; arr.forEach(function(elem) { this.push(elem * elem); }, out); out; // [1, 4, 9]
filter
方法和map
方法的异同:
相同: 用法一致, 参数是一个函数(接受三个参数), 可以接受第二参数绑定函数内部的
this
不同:
forEach
方法返回 结果true
的成员组成的一个新数组
[1, 2, 3, 4, 5].filter(function (elem, index, arr) { return index % 2 === 0; });// [1, 3, 5]
some
, every
方法和map
方法的异同:
相同: 用法一致, 参数是一个函数(接受三个参数), 可以接受第二参数绑定函数内部的
this
不同:
some
,every
方法返回 一个布尔值, 表示判断数组成员是否符合某种条件some
方法, 只要一个成员的返回值为true
, 整个方法返回值就是true
every
方法, 要所有成员的返回值为true
, 整个方法返回值才是true
对于空数组,
some
方法返回false
,every
方法返回true
, 回调函数都不会执行
reduce(), reduceRight()
reduce
方法和reduceRight
方法, 依次处理数组的每个成员, 最终累计为一个值. 除了起始方向不同, 其他完全一样.
const arr = [1, 2, 3, 4, 5]; arr.reduce(function(a, b) { console.log(a, b); return a + b; // 15})// 1 2// 3 3// 6 4// 10 5// 最后结果: 15
reduce
方法第一个参数为函数, 该函数的接受四个参数解释:
累计变量, 必须, 默认为数组的第一个成员
当前变量, 必须, 默认为数组的第二个成员
当前位置(从0开始), 可选
原数组, 可选
reduce(),
作用: 依次处理数组的每个成员, 返回累计值
参数: 接受一个函数作为参数; 第二参数可选但很重要, 用来对累计变量指定初值
返回: 累计值
我们来看看第二参数的在处理空数组时的一个用处吧.
function add(prev, cur) { return prev + cur; } [].reduce(add);// TypeError: Reduce of empty array with no initial value// 类型错误: 空数组的reduce方法没有初值[].reduce(add, 1); // 1
indexOf(), lastIndexOf()
indexOf(),
作用: 返回给定元素在数组中第一次出现的位置
参数: 指定元素; 可以接受第二参数, 表示搜索的开始位置
返回: 第一次出现的位置, 若没出现, 则返回 -1
lastIndexOf(),
作用: 返回给定元素在数组中最后一次出现的位置
参数: 指定元素
返回: 最后一次出现的位置, 若没出现, 则返回 -1
作者:lovemininal
链接:https://www.jianshu.com/p/9717379de192