1. 扩展运算符

内部调用的是数据结构的 Iterator 接口,

因此只要具有 Iterator 接口的对象,都可以使用扩展运算符 ...

如 map,,,,

[...arr]

扩展运算符(spread)是三个点(...)

将一个数组转为用逗号分隔的参数序列

    1. console.log(...[1, 2, 3]); // 1 2 3
    2.  
    3. console.log(1, ...[2, 3, 4], 5); // 1 2 3 4 5
    4.  
    5. [...document.querySelectorAll('div')]; // [<div>, <div>, <div>]
  • 主要用于函数调用
    1. function push(array, ...items) {
    2. array.push(...items);
    3. };
    4.  
    5. function add(x, y) {
    6. return x + y;
    7. };
    8.  
    9. const numbers = [4, 38];
    10. add(...numbers); //
  • 扩展运算符后面还可以放置表达式
    1. const arr = [
    2. ...(x > 0 ? ['a'] : []),
    3. 'b',
    4. ];
  • 如果扩展运算符后面是一个空数组,则不产生任何效果
    1. [...[], 1]; // [1]
  • 不再需要apply方法,将数组转为函数的参数了
    1. function f(x, y, z) {
    2. // ...
    3. }
    4.  
    5. f.apply(null, [0, 1, 2]); // ES5 的写法

    6. f(...[0, 1, 2]); // ES6的写法
    1. Math.max.apply(null, [14, 3, 77]); // ES5 的写法
    2. Math.max(...[14, 3, 77]); // ES6 的写法
    3.  
    4. // 等同于
    5. Math.max(14, 3, 77);;
    1. var arr1 = [0, 1, 2];
    2. var arr2 = [3, 4, 5];
    3.  
    4. Array.prototype.push.apply(arr1, arr2); // ES5 的写法

    5. arr1.push(...arr2); // ES6 的写法

2. 复制数组 ...

ES5 只能用变通方法来复制数组

    1. const a1 = [1, 2];
    2. const a2 = a1.concat();
    3.  
    4. a2[0] = 2;
    5. a1 // [1, 2]
  • ES6 使用 ...复制数组        但还是浅拷贝
    1. const a1 = [1, 2];
    2.  
    3. const a2 = [...a1]; // 写法一

    4. const [...a2] = a1; // 写法二

如果将扩展运算符用于数组赋值,只能放在参数的最后一位,否则会报错

  • 扩展运算符还可以将字符串转为真正的数组
    1. [...'hello']; // [ "h", "e", "l", "l", "o" ]

    好处,那就是能够正确识别四个字节的 Unicode 字符。

    1. 'x\uD83D\uDE80y'.length //
    2. [...'x\uD83D\uDE80y'].length // 3 正确返回字符串长度的函数

正确返回字符串长度

    1. function length(str) {
    2. return [...str].length;
    3. };
    4.  
    5. length('x\uD83D\uDE80y'); //

3. Array.from()

Array.from() 用于将以下两类对象转为真正的数组

  • 类似数组的对象(array-like object)
  • 遍历(iterable)的对象(包括 ES6 新增的数据结构 Set 和 Map)

任何有 length 属性的对象,都可以通过 Array.from() 转为数组,而弥补 扩展运算符 ... 就无法转换

因为 扩展运算符... 只对有 Iterator 接口的对象, 转为真正的数组

  • 实例
    1. let arrayLike = {
    2. '0': 'a',
    3. '1': 'b',
    4. '2': 'c',
    5. length: 3
    6. };
    7. var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c'] // ES5的写法

    8. let arr2 = Array.from(arrayLike); // ['a', 'b', 'c'] // ES6的写法
  • querySelectorAll() 返回的是一个 NodeList 对象。它不是数组,而是一个类似数组的对象。

这时,扩展运算符可以将其转为真正的数组,原因就在于 NodeList 对象实现了 Iterator

    1. let nodeList = document.querySelectorAll('div');

    2. let array = [...nodeList];
      let arr = Array.from(nodeList);
  • 字符串转数组,Set 对象 转 数组
    1. Array.from('hello'); // ['h', 'e', 'l', 'l', 'o']
    2.  
    3. let namesSet = new Set(['a', 'b']);
    4. Array.from(namesSet); // ['a', 'b']

4. Array.from() 还可以接受第二个参数,作用类似于数组的map方法,用来对每个元素进行处理,将处理后的值放入返回的数组

    1. Array.from(arrayLike, x => x * x);
    2.  
    3. // 等同于
    4. Array.from(arrayLike).map(x => x * x);
    5.  
    6. Array.from([1, 2, 3], (x) => x * x); // [1, 4, 9]
  • 将数组中 布尔值为 false 的成员转为 0
    1. Array.from([1, , 2, , 3], (n) => n || 0); // [1, 0, 2, 0, 3]
  • 返回各种数据的类型
    1. function typesOf () {
    2. return Array.from(arguments, value => typeof value)
    3. };
    4. typesOf(null, [], NaN); // ['object', 'object', 'number']
  • 完美计算 length
    1. function countSymbols(string) {
    2. return Array.from(string).length;
    3. }:

    因为它能正确处理各种 Unicode 字符,可以避免 JavaScript 将大于\uFFFF的 Unicode 字符,算作两个字符的 bug

  • 传入 Array.from() 第三个参数,用来绑定 this

4. Array.of

将一组值,转换为数组

    1. Array.of(3, 11, 8); // [3,11,8]
    2. Array.of(3); // [3]
    3. Array.of(3).length; //
  • 基本上可以用来替代 Array() 或 new Array(),并且 不存在 由于 参数不同 导致重载。它的行为非常统一
    1. Array.of(); // []
    2. Array.of(undefined); // [undefined]
    3. Array.of(1); // [1]
    4. Array.of(1, 2); // [1, 2]

5. 数组实例的 Array.prototype.copyWithin(target, start = 0, end = this.length)

数组实例的 arr.copyWithin()

在当前数组内部,将指定位置的成员复制到其他位置(会覆盖原有成员),然后返回当前数组

也就是说,使用这个方法,会修改当前数组。

target(必需)        从 target 开始替换数据。如果为负值,表示倒数。
start(可选)       从 start 开始读取数据,默认为 0。如果为负值,表示倒数。
end(可选)       到 end 前停止读取数据,默认等于数组长度。如果为负值,表示倒数。

这三个参数都应该是数值,如果不是,会自动转为数值

    1. [1, 2, 3, 4, 5].copyWithin(0, 3); // [4, 5, 3, 4, 5]
    1. // 将3号位复制到0号位
    2. [1, 2, 3, 4, 5].copyWithin(0, 3, 4); // [4, 2, 3, 4, 5]
    3.  
    4. // -2相当于3号位,-1相当于4号位
    5. [1, 2, 3, 4, 5].copyWithin(0, -2, -1); // [4, 2, 3, 4, 5]
    6.  
    7. // 将3号位复制到0号位
    8. [].copyWithin.call({length: 5, 3: 1}, 0, 3); // {0: 1, 3: 1, length: 5}
    9.  
    10. // 将2号位到数组结束,复制到0号位
    11. let i32a = new Int32Array([1, 2, 3, 4, 5]);
    12. i32a.copyWithin(0, 2); // Int32Array [3, 4, 5, 4, 5]
    13.  
    14. // 对于没有部署 TypedArray 的 copyWithin 方法的平台 需要采用下面的写法
    15. [].copyWithin.call(new Int32Array([1, 2, 3, 4, 5]), 0, 3, 4);; // Int32Array [4, 2, 3, 4, 5]

6. arr.find()

找出第一个符合条件的数组成员

它的参数是一个回调函数,所有数组成员依次执行该回调函数,直到找出第一个返回值为 true 的成员,然后返回该成员

如果没有符合条件的成员,则返回 undefine

    1. [1, 4, -5, 10].find((n) => n < 0); // -5
    1. [1, 5, 10, 15].find(function(ele, index, arr) {
    2. return ele > 9;
    3. }); //

7. arr.findIndex()

返回第一个符合条件的数组成员的位置

如果所有成员都不符合条件,则返回-1

    1. [1, 5, 10, 15].findIndex(function(value, index, arr) {
    2. return value > 9;
    3. }); //
  • arr.find() arr.findIndex() 都可以接受第二个参数,用来绑定回调函数的this对象
    1. let person = {name: 'John', age: 20};
    2. [10, 12, 26, 15].find(function(ele){
    3. return v > this.age;
    4. }, person); //
  • arr.find() 和 arr.findIndex() 都可以发现NaN,弥补了数组的 indexOf 方法的不足

内部其实借助 Object.is 发现了 NaN

8. arr.fill() 

使用给定值填充一个数组

第一个参数: 给定值

第二个参数: 填充起始位置

第三个参数: 填充结束位置        end 不会被填充

    1. ['a', 'b', 'c'].fill(7); // [7, 7, 7]
    2.  
    3. new Array(3).fill(7); // [7, 7, 7]
    4.  
    5. ['a', 'b', 'c'].fill(7, 1, 2); // ['a', 7, 'c']
  • 用于空数组的初始化非常方便。数组中已有的元素,会被全部抹去
  • 如果填充的类型为对象,那么被赋值的是同一个内存地址的对象,而不是深拷贝对象
    1. let arr = new Array(3).fill({name: "Mike"});
    2. arr[0].name = "Ben";
    3. console.log(arr); // [{name: "Ben"}, {name: "Ben"}, {name: "Ben"}]
    4.  
    5. let arr = new Array(3).fill([]);
    6. arr[0].push(5);
    7. console.log(arr); // [[5], [5], [5]]

9. ES6 遍历数组新方法

都返回一个遍历器对象,可以用 for...of 循环进行遍历

arr.entries()        是对键值对的遍历

arr.keys()        是对键名的遍历

arr.values()        是对键值的遍历

arr.entries()

    1. for (let [index, elem] of ['a', 'b'].entries()) {
    2. console.log(index, elem);
    3. };
    4. // 0 "a"
    5. // 1 "b"

arr.keys()

    1. for (let index of ['a', 'b'].keys()) {
    2. console.log(index);
    3. };
    4. //
    5. //

arr.values()

    1. for (let ele of ['a', 'b'].values()) {
    2. console.log(ele);
    3. };
    4. // 'a'
    5. // 'b'
  • 不使用 for...of 循环,可以手动调用遍历器对象的 next() 方法,进行遍历
    1. let letter = ['a', 'b', 'c'];
    2. let entries = letter.entries();
    3. console.log(entries.next().value); // [0, 'a']
    4. console.log(entries.next().value); // [1, 'b']
    5. console.log(entries.next().value); // [2, 'c']

10. arr.includes()

返回一个布尔值,表示某个数组是否包含 给定值,与字符串的 includes 方法类似

第一个参数: 给定值

第二个参数: 表示搜索的起始位置,默认为 0

如果第二个参数为负数,则表示倒数的位置,

如果这时它大于数组长度(比如第二个参数为-4,但数组长度为3),则会重置为从 0 开始

    1. [1, 2, 3].includes(2); // true
    2. [1, 2, 3].includes(4); // false
    3. [1, 2, NaN].includes(NaN); // true
  • Map 和 Set 数据结构有一个has方法,需要注意与includes区分
  • Map 结构的has方法,是用来查找键名的

Map.prototype.has(key)

WeakMap.prototype.has(key)

Reflect.has(target, propertyKey)

  • Set 结构的has方法,是用来查找值的

Set.prototype.has(value)

WeakSet.prototype.has(value)

11. arr.flat()

将嵌套的数组 "拉平",变成一维的数组。该方法返回一个新数组,对原数据没有影响

    1. [1, 2, [3, 4]].flat(); // [1, 2, 3, 4]

arr. flat() 只有一个参数,指定“拉平” 多少层,默认为1

传递一个整数,表示想要拉平的层数,

如果不管有多少层嵌套,都要转成一维数组,可以用 Infinity 关键字作为参数

    1. [1, 2, [3, [4, 5]]].flat(); // [1, 2, 3, [4, 5]]
    2.  
    3. [1, 2, [3, [4, 5]]].flat(2); // [1, 2, 3, 4, 5]
    4.  
    5. [1, [2, [3]]].flat(Infinity);    // [1, 2, 3]


  • 如果原数组有空位,arr.flat() 处理后会去掉
    1. [1, 2, , 4, 5].flat(); // [1, 2, 4, 5]

12. arr.flatMap()

对原数组的每个成员执行一个函数(相当于执行Array.prototype.map()),

然后对返回值组成的数组 arr 执行 arr.flat()方法。

该方法返回一个新数组,不改变原数组

参数:

第一个参数: 回调函数

第二个参数: 绑定 this 指向

    1. // 相当于 [[[2]], [[4]], [[6]], [[8]]].flat()
    2. [1, 2, 3, 4].flatMap(x => [[x * 2]]); // [[2], [4], [6], [8]]

13. 数组的空位

数组的某一个位置没有任何值。比如,Array 构造函数返回的数组都是空位

ES5 对空位的处理,已经很不一致了,大多数情况下会忽略空位

ES6 则是明确将空位转为 undefined,而不会忽略空位

    1. Array.from(['a',,'b']); // [ "a", undefined, "b" ]

ECMA Script 6_数组的扩展_扩展运算符的更多相关文章

  1. ECMA Script 6_解构赋值_模式匹配

    解构赋值 从数组中提取值,按照对应位置,对变量赋值 只要等号右边的值不是对象或数组,就先将其转为对象. 由于 undefined 和 null 无法转为对象,所以对它们进行解构赋值,都会报错 let ...

  2. ECMA Script 6_字符串_扩展_字符 是4字节还是2字节?_模板字符串

    ES6 字符串扩展 ES6 加强了对 Unicode 的支持,并且扩展了字符串对象 字符 的 Unicode 表示法 允许采用 \uxxxx 形式表示一个字符, 其中 xxxx 表示字符的 Unico ...

  3. ECMA Script 6_函数的扩展

    ES6规定只要函数参数使用了默认值.解构赋值.或者扩展运算符, 那么函数内部就不能显式设定为严格模式,否则会报错 1. 参数的默认值 ES6 允许为函数的参数设置默认值,即直接写在参数定义的后面 函数 ...

  4. ECMA Script 6_对象的扩展

    对象 1. ES6 允许直接写入变量和函数,作为对象的属性和方法 const foo = 'bar'; /*****************属性的优化********************/ con ...

  5. ECMA Script 6_数值的扩展

    1. 二进制 和 八进制 新的表示法 前缀 0b(或0B) 表示 二进制 前缀 0o(或 0O )表示 八进制 console.log(0b111110111 === 503); // true co ...

  6. ECMA Script 6_简单介绍

    ECMAScript 6 ECMA 组织 前身是 欧洲计算机制造商协会 指定和发布脚本语言规范,标准在每年的 6 月份正式发布一次,作为当年的正式版本 这样一来,就不需要以前的版本号了,只要用年份标记 ...

  7. ECMA Script 6_唯一容器 Set_映射容器 Map

    唯一容器 Set ES6 提供了新的数据结构 Set Set 结构没有键名,只有键值(或者说 键名 和 键值 是同一个值) 它类似于数组,但是成员的值都是唯一的,没有重复的值 Set 内部判断两个值是 ...

  8. ECMA Script 6_模块加载方案 ES6 Module 模块语法_import_export

    1. 模块加载方案 commonJS 背景: 历史上,JavaScript 一直没有模块(module)体系, 无法将一个大程序拆分成互相依赖的小文件,再用简单的方法拼装起来. 其他语言都有这项功能: ...

  9. ECMA Script 6_异步编程之 Promise

    Promise 对象 异步编程 方案,已同步的方式表达异步的代码,解决回调地狱的问题 比传统的解决方案——回调函数和事件——更合理和更强大 是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步 ...

随机推荐

  1. [物理学与PDEs]第2章第2节 粘性流体力学方程组 2.1 引言

    1.  实际的流体与理想流体的主要区别在于: 前者具有粘性 (内摩擦) 和热传导. 2.  内摩擦 (1)  当两层流体有相对运动时, 方有摩擦力; 它是一种内力; 单位面积上所受的内力称为应力; 而 ...

  2. Groovy 设计模式 -- 装饰器模式

    http://groovy-lang.org/design-patterns.html#_chain_of_responsibility_pattern 装饰器模式, 起到美化原始对象的作用. 一个被 ...

  3. javascript基础 之 json

    1,json是用于存储和传输的数据格式 全称:JSON 英文全称 JavaScript Object Notation json转化为javascript的规则: 数据为 键/值 对. 数据由逗号分隔 ...

  4. LeetCode第十题-正则表达式匹配

    Regular Expression Matching 问题简介:给定字符串,给定匹配模式,判断字符串是否满足匹配模式 问题详解:一共有两种特殊模式: ‘.’ 匹配任何单个字符 ‘*’ 匹配前面元素的 ...

  5. Hack Programming

    计算机由ROM(instruction memory).RAM(data memory).CPU组成,其关系如下图 在计算中存在3种寄存器:D.A.M.其中D是data register,A是addr ...

  6. codeforces 893F - Physical Education Lessons 动态开点线段树合并

    https://codeforces.com/contest/893/problem/F 题意: 给一个有根树, 多次查询,每次查询对于$x$i点的子树中,距离$x$小于等于$k$的所有点中权值最小的 ...

  7. C++11新特性(1)

    1.long long 类型 C++11新增了long long 和 unsigned long long 类型,为长整型和无符号长整型 long long 类型的数据占用8个字节(64位),取值范围 ...

  8. python3 基础语法(一)

    一.标识符: 第一个字符必须是字母表中字母或下划线 “_” . 例如: #!/usr/bin/env python #coding=utf-8 a = 3 _aa = 3 a3 = 3 _aa3 = ...

  9. C++\CLI语法 在项目中的使用

    通常情况下,对一个标准的com组件进行集成,网上普遍使用的方式有: 1.#import *.dll 或 #import *.ocx的方式,VS编译器重新编译后,就会自动生成组件对应的*.tlh文件,该 ...

  10. Redis实战 - 1.String和计数器

    在.NET Core 项目中操练String 使用 StackExchange.Redis 访问 Redis static void Main(string[] args) { using (Conn ...