为了账号安全,请及时绑定邮箱和手机立即绑定

JS 中的 Array对象

标签:
JavaScript

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方法, 会跳过数组的空位, 不会跳过undefinednull


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方法第一个参数为函数, 该函数的接受四个参数解释:

  1. 累计变量, 必须, 默认为数组的第一个成员

  2. 当前变量, 必须, 默认为数组的第二个成员

  3. 当前位置(从0开始), 可选

  4. 原数组, 可选

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


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消