如没有特别说明,测试宿主环境为Node.js

文章目录

  • 前言
  • 一、逗号创建数组
  • 二、容易忽略的.length
  • 三、检测数组的两种方法
  • 四、迭代器方法(返回迭代器)
  • 五、迭代方法(返回boolean值或者Array对象)
  • 六、复制和填充方法
  • 七、栈与队列方法
  • 八、翻转与排序

前言

除了Object之外,Array应该ECMAScript中最常用的类型了,但和其他语言不一样,ECMAScript中的数组长度是可变的,而且由于ECMAScript的弱类型,这也使得数组Array中存取的类型可以是混杂的,例如数组的第一个元素可能是number类型,第二个可能是string类型,第三个可能又是Object,但通常我们不会这么做,更多地是使用统一的规范


一、逗号创建数组

我们来看两种有意思几种的逗号数组创建方式:

  1. 第一种

    var arr = [,,,];           //创建包含三个空位的数组
    console.log(arr.length);   // => 3
    console.log(arr);          // => [ <3 empty items> ]
    
  2. 第二种

    var arr = [2,,,6];          //创建包含四个空位的数组
    console.log(arr.length);   // => 4
    console.log(arr);          // => [ 2, <2 empty items>, 6 ]
    
  3. 第三种

    var arr = [2,,,];           //创建包含三个空位的数组
    console.log(arr.length);   // => 3
    console.log(arr);          // => [ 2, <2 empty items> ]
    
  4. 第四种

    var arr = [,,1,];           //创建包含四个空位的数组
    console.log(arr.length);   // => 3
    console.log(arr);          // => [ <2 empty items>, 1 ]
    
  5. 第五种

    var arr = [,,,3];           //创建包含四个空位的数组
    console.log(arr.length);   // => 4
    console.log(arr);          // => [ <3 empty items>, 3 ]
    

不知道你所预期的结果和实际输出的有没有区别,得到这样结果的原因是从ES5规范开始就允许在列表(数组值,属性列表)末尾多加一个逗号(在实际处理中会被忽略不计)

那如何简便判断数组的length呢?

如果你读懂了上文的解释,你或许猜到了,如果数组最后一个是, 控制台输出会忽略这个, 然后正常的思维计算数组长度,现在利用这个规律返回看看上面的五个示例,得到的结果是不是这样的呢?

数组创建的静态方法:
关于数组创建,这里我引入Array.from()Array.of()两个方法

  1. Array.from()

    //字符串会被拆分为单字符数组
    console.log(Array.from("hello"));     // => ["h","e","l","l","o"];//对现有数组进行复制
    const arr1 = [1,2,3,4,5];
    const console.log(Array.from(arr1));    // => [1,2,3,4,5]
    console.log(arr1 === arr2);              // => flase//还可接受第二个可选的映射函数参数,这个函数可以直接增强新数组的值,类似于调用函数map()
    const arr3 = [2,3,4,5];
    console.log(Array.from(arr3,x => x**2)); // =>[4,9,14,25]  注:** 相当于执行了Math.pow()函数
    
  2. Array.of()
    这个函数主要用在把一组参数转换为数组

    //以前我们通常会用如下函数返回一系列参数组成的数组
    function fn() {console.log(Array.prototype.slice.call(arguments));
    }
    fn(1, 2, 3, 4); // => [1,2,3,4]
    //但现在我们有了更简便的方法
    console.log(Array.of(1,2,3,4)); // => [1,2,3,4]
    

二、容易忽略的.length

JavaScript的数组长度length具有一些其他语言没有的特性

  1. 数组长度可变,可以更改length的值来修改数组长度

    let arr = ["a","b","c","d"];
    arr.length = 5;
    console.log(arr); // =>  ["a","b","c","d",undefined,underfined]; 注:未定义的单元用undefined填充
    arr.lengeh = 2;
    console.log(arr); // =>  ["a","b"]; 注:缩小数组长度会覆盖以前的以定义的单元
    
  2. 插入问题,设置某位置的值,有可能会改变数组长度,哪怕设置为undefined
    let arr = [2,4,6,8];
    console.log(arr); // => [ 2, 4, 6, 8 ]
    console.log(arr.length); // => 4arr[80] = 100;
    console.log(arr);   // => [ 2, 4, 6, 8, <76 empty items>, 100 ]
    console.log(arr.length); // => 81arr[99] = undefined;
    console.log(arr);   // => [ 2, 4, 6, 8, <76 empty items>, 100, <18 empty items>, undefined ]
    console.log(arr.length); // => 100
    

三、检测数组的两种方法

说到检测数组,不管是在Java中还是JavaScript中,我们都不由想到instanceof操作符
这是正确的,你可以使用如下方法检测数组

const arr = [12,2,3,4];
console.log(arr instanceof Array);  // => true

我希望你也能知道还有一种少见但重要的检测方法,试想我们有两个框架在同一个网页中,涉及两个不同的全局执行上下文,就可能有两个不同版本的Array构造函数,如果把一个用第一个框架的声明的数组传入另一个框架,在用instanceof Array检测是否是数组,显然此时会返回false

因为 instanceof Array操作代表的并不是像我们理解的那样判断一个对象是不是数组,而是告诉我们该对象是否是当前全局作用域下的Array的实例

为了解决这个问题,ECMAScript提供了Array.isArray()方法,这个方法的目的就是确定一个值是否为数组,如下:

let arr = ['a','b','c','d'];
if (Array.isArray(arr)) {console.log('yes');
}

四、迭代器方法(返回迭代器)

我们知道,对象Object有三个静态方法Object.keys()、Object.values()、Object.entries()

同样的,ECMAScript也在Array的对象原型上为我们添加了类似方法来实现数组的迭代

  1. Array.prototype.keys()
    这个方法返回数组 索引 的迭代器

    let arr = [3,5,7,9,11];
    console.log(Array.from(arr.keys())); // => [ 0, 1, 2, 3, 4 ]
    
  2. Array.prototype.values()
    这个方法返回数组 值 的迭代器

    let arr = [3,5,7,9,11];
    console.log(Array.from(arr.values()));  // => [ 3, 5, 7, 9, 11 ]
    
  3. Array.prototype.entries()
    这个方法返回数组 索引/值 对的迭代器

    let arr = [3,5,7,9,11];
    console.log(Array.from(arr.entries()));  // => [ [ 0, 3 ], [ 1, 5 ], [ 2, 7 ], [ 3, 9 ], [ 4, 11 ] ]
    

对,如你所想,Array.from()方法还可以接收迭代器,转为数组


五、迭代方法(返回boolean值或者Array对象)

你可能意识到了,上面的三种迭代器方法方法只能帮我们输出数组的内容,并不能做一些判断和操作,那么接下来的五个迭代方法将会对你操作数组提供更便捷的方式,传入的第一个参数为 断言函数,在某些方法中通常简写为匿名函数,如下就是采用匿名函数的形式,断言函数的三个参数分别为 值 、索引、该数组本身

  1. every():

对数组的每一项都运行传入的参数,如果对每一项函数都返回true,则这个方法返回true
像every翻译过来一样(全部),我们可以用这个方法来判断某个数组的所有值是否都满足某个条件,例如

let arr = [24,56,87,33,45];
console.log(arr.every((item, index, array) => item > 10));  //=> true  注:5个值都大于10,返回true
  1. some():

对数组的每一项都运行传入的参数, 如果有一项函数返回true,则这个方法返回true
像some翻译过来一样(某些),我们可以用这个方法来判断某个数组的某个值都满足某个条件

let arr = [24,56,87,33,45];
console.log(arr.some((item, index, array) => item > 80));  //=> true  注:87大于80,返回true
  1. filter():

对数组的每一项都运行传入的参数,函数返回true的项将会组成数组后返回
像filter翻译过来一样(过滤器),我们只挑选符合我们需求的值组成数组并返回

let arr = [24,56,87,33,45];
console.log(arr.filter((item, index, array) => item > 35));  //=> [56, 87, 45]  注:返回大于35的值组成的数组
  1. forEach():

对数组的每一项都运行传入的参数,类似于for循环,只是forEach会将每一项函数返回值组成数组返回

let arr = [24, 56, 87, 33, 45];
console.log(arr.filter((item, index, array) => arr[index])); //=>[ 24, 56, 87, 33, 45 ]//等价于
let arr_2 = [];
for (let i = 0; i < arr.length; i++) {arr_2.push(arr[i]));
}
console.log(arr_2);   //=>[ 24, 56, 87, 33, 45 ]
  1. map():

对数组的每一项都运行传入的参数,将每一项函数return返回的值组成数组后返回
可用此方法对数组的值进行操作改变后返回

let arr = [24, 56, 87, 33, 45];
console.log(arr.map(item, index, array) => item * 2);  //=>[ 48, 112, 174, 66, 90 ]

尽管有了如上的迭代器方法,可以很容易对数组进行我们想要的的操作,但我们还是感到对数组某些方面没有足够边便捷的操作,例如如何快速在头部和尾部添加值或者删减值(你可能注意到上文用了一次push函数),又或者如何对数组进行快速整齐地赋值,接下来两节着重围绕此进行说明


六、复制和填充方法

ES6新增了两个批量复制和填充数组的方法:

  1. Array.prototype.fill(value[, start[, end]])

    //一个参数时,默认value填充数组所有元素
    let arr = [1,2,3,4,5,6];
    arr.fill(5);
    console.log(arr); // =>[5,5,5,5,5,5]; 注:全被覆盖-//两个参数时,使用value填充大于等于start的元素
    let arr = [4,8,6,5,3];
    arr.fill(2,5);
    console.log(arr); // =>[4,2,2,2,3]; 注:8,6,5都大于等于5,被覆盖//三个参数时,使用value填充大于等于start,小于等于end的元素
    let arr = [4,8,6,5,3];
    arr.fill(2,5,6);
    console.log(arr); // =>[4,8,2,2,3]; 注:6,5都大于等于5,小于等于6,被覆盖
    
  2. Array.prototype.copyWithin(target[, start[, end]])
    //一个参数时,复制索引0的开始的内容,插值到索引start开始的地方
    let arr = [1,2,3,4,5,6];
    arr.copyWithin(2);
    console.log(arr); // =>[ 1, 2, 1, 2, 3, 4 ]; //注:复制索引0的开始的内容,插值到索引为2开始的地方//两个参数时,复制索引start的开始的内容,插值到索引target开始的内容
    let arr = [1, 2, 3, 4, 5, 6];
    arr.copyWithin(2, 3);
    console.log(arr); // =>[ 1, 2, 4, 5, 6, 6 ];  // 注:复制4,5,6,插值到下标为2开始的位置//三个参数时,复制索大于等于start,小于end的内容,插值到索引target开始的地方
    let arr = [1, 2, 3, 4, 5, 6];
    arr.copyWithin(2, 3, 5);
    console.log(arr); // =>[ 1, 2, 4, 5, 5, 6 ];  注:复制4,5,插入到索引值为2的地方
    

copyWithin()和fill()的参数满足以下条件

  • 负值索引从数组末尾开始计算
  • 静默忽略超出数组边界,0长度及方向反向的索引范围
  • 索引值有部分可用,则用该可用的部分

七、栈与队列方法

  1. Array.protype.push()

    //从数组尾部添加元素,返回新数组长度
    let arr = [1,2,3,4];
    console.log(arr.push(5,6)); // => 6
    console.log(arr);   // => [1,2,3,4,5,6];
    
  2. Array.protype.pop()
    //从数组尾部删除一个元素,返回该删除的元素
    let arr = ["a","b","c","d"];
    console.log(arr.pop()); // => "d"
    console.log(arr);   // => ["a","b","c"];
    
  3. Array.protype.unshift()
    //从数组头部添加元素,返回新数组长度
    let arr = [1,2,3,4];
    console.log(arr.unshift(7,8,9)); // => 7
    console.log(arr);   // => [7,8,9,1,2,3];
    
  4. Array.protype.shift()
     //从数组头部删除一个元素,返回该删除的元素
    let arr = [1,2,3,4];
    console.log(arr.shift()); // => 1
    console.log(arr);   // => [2,3,4];
    

到现在应该算了解了操作数组的大部分方法,我们已经能对数组内部元素做许多操作了,接下来更深入了解数组本身的一些基本操作,如数组翻转,排序和数组之间的连接


八、翻转与排序

JavaScript -- Array进阶详解相关推荐

  1. 最全 JavaScript Array 方法 详解

    大家好,我是若川.最近组织了源码共读活动,感兴趣的可以点此加我微信 ruochuan12 参与,每周大家一起学习200行左右的源码,共同进步.同时极力推荐订阅我写的<学习源码整体架构系列> ...

  2. javaScript函数模块详解

    javaScript函数模块详解 ​ 函数实际上是对象,每个函数都是Function类型的实例,而Function也有属性和方法,和其他引用类型一样 可以将函数名想象成指针,函数想象成对象 ​ 注意, ...

  3. 史上最全JavaScript数组对象详解(二)

    JavaScript数组对象详解(二) 上一篇博客我们讲到了JavaScript数组对象的创建,访问和属性,接下来一篇博客主要讲一下JavaScript数组对象的方法及使用.说到数组的方法,主要分为两 ...

  4. JavaScript的函数详解

    JavaScript的函数详解 一.什么是函数 二.函数的使用 1.函数的声明 2.函数的调用 3.函数的参数:参入运算的数据 (1)形参(形式参数) (2)实参(实在参数): (3)参数之间的数据传 ...

  5. javascript BOM对象详解

    javascript BOM对象详解 目标:本章节将分为9点详细介绍有关BOM对象的知识点 1.什么是BOM 2.BOM的构成 3.顶级对象window 4.window对象常见事件(页面加载事件和体 ...

  6. 2接口详解_TS入门笔记2——TS接口进阶详解

    TS入门笔记--TS接口进阶详解 一.为什么需要接口? let obj:object; // 定义了一个只能保存对象的变量 // obj = 1; // obj = "123"; ...

  7. JavaScript 运行机制详解(理解同步、异步和事件循环)

    1.为什么JavaScript是单线程? JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事.那么,为什么JavaScript不能有多个线程呢?这样能提高效率啊. Java ...

  8. 好程序员技术分析JavaScript闭包特性详解

    为什么80%的码农都做不了架构师?>>>    好程序员技术分析JavaScript闭包特性详解,今天来总结一下js闭包的那些事,以及遇到的坑和解决方法,希望对你有所帮助. 是的,没 ...

  9. 我看朴灵评注阮一峰的《JavaScript 运行机制详解:再谈Event Loop》

    阮一峰和朴灵对我来说都是大牛,他们俩的书我都买过,阮老师的译作<软件随想录>和朴灵的<深入浅出node.js>.这个事情已经过了4个月了,所以我拿来讲应该也没啥问题. 这件事情 ...

最新文章

  1. R可视化绘制对数正态分布(Log Normal Distribution)
  2. Sql 常用日子转换Convert
  3. linux电脑系统投到电视,教你如何在Linux操作系统下观看电视节目
  4. 数据结构---排序算法的总结
  5. 2019-02-24-算法-进化
  6. ETL异构数据源Datax_日期增量同步_13
  7. arcgis engine设置数据源路径_不用ArcGIS做前期分析,你是不是想被辞!
  8. mac 安装mysql
  9. Gym - 100783E
  10. 文本主题模型之LDA(二) LDA求解之Gibbs采样算法
  11. reactNative之react-native-picker
  12. navicat连接mangoDB数据库并使用
  13. java解析project mpp文件_Java利用mpxj解析mpp格式文件
  14. Oracle数据库启动过程详解
  15. 《梁宁·产品思维30讲》
  16. Python量化交易平台:JQData | API使用文档(转)
  17. 四种内容付费盈利模式介绍
  18. Dart(5)-内置类型
  19. vue+openlayers实现地图打点
  20. linux命令之-dmesg详解

热门文章

  1. Edge浏览器系列:win10如何关闭Alt+tab只切换Edge浏览器的网页
  2. 华为认证Datacom一些问答
  3. 【超用心整理】Markdown常用语法介绍,看这一个就够了
  4. 赤兔ctcms2.0.9最新破解授权版|修复bug|采集入库规则自定义...
  5. 华为云计算HCIA题目1
  6. html-css文字特效,7款震撼人心的HTML5CSS3文字特效_html/css_WEB-ITnose
  7. 宏碁(Acer)商祺SQX4270 140N加固态硬盘,加内存
  8. 王润涵:如何用链脉名片开启电商新模式“新零售”
  9. 《道德经》第二十五章
  10. 表单提交与后台PHP如何接口?