ES6新特性

ES6 语法

块级作用域、const、let

  • 在 ES6 之前会存在变量提升,提升到函数作用域顶部
  • let 与 const 声明的变量解决了这种问题,因为他们是块级作用域, 在代码块(用{}表示)中使用
  • let 或 const 声明变量, 该变量会陷入暂时性死区直到该变量的声明被处理.
  • 使用 let 声明的变量可以重新赋值,但是不能在同一作用域内重新声明
  • 使用 const 声明的变量必须赋值初始化,但是不能在同一作用域类重新声明也无法重新赋值.

字符串模板

  • 在 ES6 之前,将字符串连接到一起的方法是+或者 concat()方法
  • 模板字面量本质上是包含嵌入式表达式的字符串字面量
  • 模板字面量用倒引号 ( `` )(而不是单引号 ( ‘’ ) 或双引号( “” ))表示,可以包含用 ${expression} 表示的占位符

解构

在 ES6 中,可以使用解构从数组和对象提取值并赋值给独特的变量

解构数组的值

1
2
3
const point = [10, 25, -34];
const [x, y, z] = point;
console.log(x, y, z);

[]表示被解构的数组, x,y,z 表示要将数组中的值存储在其中的变量, 在解构数组是, 还可以忽略值, 例如 const[x,,z]=point,忽略 y 坐标.

解构对象中的值

1
2
3
4
5
6
7
const gemstone = {
type: "quartz",
color: "rose",
karat: 21.29,
};
const { type, color, karat } = gemstone;
console.log(type, color, karat);

花括号 { } 表示被解构的对象,type、color 和 karat 表示要将对象中的属性存储到其中的变量

对象字面量简写法

  • 使用和所分配的变量名称相同的名称初始化对象时如果属性名称和所分配的变量名称一样,那么就可以从对象属性中删掉这些重复的变量名称。
  • 在 ES6 中匿名函数不需要 function 关键字

for…of 循环

  • for…of 循环是最新添加到 JavaScript 循环系列中的循环

  • 它结合了其兄弟循环形式 for 循环和 for…in 循环的优势,可以循环任何可迭代(也就是遵守可迭代协议)类型的数据。默认情况下,包含以下数据类型:String、Array、Map 和 Set,注意不包含 Object 数据类型(即 {})。默认情况下,对象不可迭代

  • for 循环的最大缺点是需要跟踪计数器和退出条件。虽然 for 循环在循环数组时的确具有优势,但是某些数据结构不是数组,因此并非始终适合使用 loop 循环。

  • for…in 循环依然需要使用 index 来访问数组的值。当你需要向数组中添加额外的方法(或另一个对象)时,for…in 循环会带来很大的麻烦。因为 for…in 循环循环访问所有可枚举的属性,意味着如果向数组的原型中添加任何其他属性,这些属性也会出现在循环中。

  • forEach 循环 是另一种形式的 JavaScript 循环。但是,forEach() 实际上是数组方法,因此只能用在数组中。也无法停止或退出 forEach 循环。如果希望你的循环中出现这种行为,则需要使用基本的 for 循环。

  • for…of 循环用于循环访问任何可迭代的数据类型。for…of 循环的编写方式和 for…in 循环的基本一样,只是将 in 替换为 of,可以忽略索引。

    1. 建议使用复数对象名称来表示多个值的集合。这样,循环该集合时,可以使用名称的单数版本来表示集合中的单个值。例如,for (const button of buttons) {…}。

    2. for…of 循环还具有其他优势,解决了 for 和 for…in 循环的不足之处。你可以随时停止或退出 for…of 循环。

      1
      2
      3
      4
      5
      6
      for (const digit of digits) {
      if (digit % 2 === 0) {
      continue;
      }
      console.log(digit);
      }
    3. 不用担心向对象中添加新的属性。for…of 循环将只循环访问对象中的值。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      Array.prototype.decimalfy = function () {
      for (i = 0; i < this.length; i++) {
      this[i] = this[i].toFixed(2);
      }
      };

      const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

      for (const digit of digits) {
      console.log(digit);
      }

展开运算符

展开运算符(用三个连续的点 (…) 表示)是 ES6 中的新概念,使你能够将字面量对象展开为多个元素

  • 展开运算符的一个用途是结合数组。

    1. 如果你需要结合多个数组,在有展开运算符之前,必须使用 Array 的 concat() 方法。
    2. 使用展开符来结合数组
      1
      const arr = [...arr1, ...arr2];
  • 使用展开运算符将数组展开为多个元素, 使用剩余参数可以将多个元素绑定到一个数组中.剩余参数也用三个连续的点 ( … ) 表示,使你能够将不定数量的元素表示为数组.

    1. 将变量赋数组值时:

      1
      2
      const order = [20.17, 18.67, 1.5, "cheese", "eggs", "milk", "bread"];
      const [total, subtotal, tax, ...items] = order;
    2. 可变参数函数,对于参数不固定的函数,ES6 之前是使用参数对象(arguments)处理,在 ES6 中使用剩余参数运算符则更为简洁,可读性提高

      ES6 之前

      1
      2
      3
      4
      5
      6
      7
      function sum() {
      let total = 0;
      for (const argument of arguments) {
      total += argument;
      }
      return total;
      }

      ES6

      1
      2
      3
      4
      5
      6
      7
      function sum(...nums) {
      let total = 0;
      for (const num of nums) {
      total += num;
      }
      return total;
      }

ES6 箭头函数

  • 普通函数可以是函数声明或者函数表达式, 但是箭头函数始终都是表达式, 全程是箭头函数表达式, 因此仅在表达式有效时才能使用,包括:
    1. 存储在变量中
    2. 当做参数传递给函数
    3. 存储在对象的属性中
  • 如果函数的参数只有一个,不需要使用()包起来,但是只有一个或者多个, 则必须需要将参数列表放在圆括号内
  • 一般箭头函数都只有一个表达式作为函数主题,这种函数表达式形式称为简写主体语法:
    1. 在函数主体周围没有花括号
    2. 自动返回表达式
  • 但是如果箭头函数的主体内需要多行代码, 则需要使用常规主体语法:
    1. 它将函数主体放在花括号内
    2. 需要使用 return 语句来返回内容
  • 解决 this 指向问题。ES6 之前,通过将 this 值分配给封闭的变量,可以解决 this 问题,使用箭头函数则不用绑定 this

默认参数函数

JavaScript 默认参数在编写函数时非常有用。在调用函数时,如果缺少参数,则默认参数功能允许你为函数参数分配默认值,而不是将其定义为 undefined。

1
2
3
4
5
function animal(type = "cat") {
console.log(type);
}

animal();

模块化 import export

  • ES6 之前的 JavaScript 一直没有模块化的体系,无法将一个庞大的 js 工程拆分成一个个功能相对对立但相互依赖的小工程,再用一种简单的方法把这些小工程连接在一起
  • 这有可能导致两个问题:
    1. 一方面 js 代码变得很臃肿,难以维护
    2. 另一方面我们常常得很注意每个 script 标签在 html 中的位置,因为它们通常有依赖关系,顺序错了可能就会出 bug
  • 而现在我们有了 es6 的 module 功能,它实现非常简单,可以成为服务器和浏览器通用的模块解决方案。
  • ES6 模块的设计思想,是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS 和 AMD 模块,都只能在运行时确定这些东西。

基本写法

1
2
3
4
5
// index.js
import animal from "./content";

// content.js
export default "A cat";

输出多个变量

1
2
3
4
5
6
7
8
// content.js
let name = "zhangsan";
let age = 25;
function intro() {
return `我是${name}!今年${age}岁了`;
}

export { name, age, intro };

如果你不想暴露模块当中的变量名字,可以通过 as 来进行操作

1
2
// content.js
export { name as a, age as b, intro as c };

导入整个模块

1
2
// index.js
import * as people from "./content.js";

默认导出

  • 一个模块只能有一个默认导出,对于默认导出,导入的名称可以和导出的名称不一致。

  • 可以将所有需要导出的变量放入一个对象中,然后通过 export default 进行导出

    1
    2
    3
    4
    5
    6
    export default {
    fun() {
    return "默认导出一个方法";
    },
    name: "lisi",
    };
  • 同样也支持混合导出

    1
    2
    3
    4
    5
    6
    7
    8
    export default {
    fun() {
    return "默认导出一个方法";
    },
    name: "lisi",
    };

    export var age = 30;

重命名 export 和 import

如果导入的多个文件中,变量名字相同,即会产生命名冲突的问题,为了解决该问题,ES6 为提供了重命名的方法,当你在导入名称时可以这样做:

1
2
3
4
5
6
7
8
// test1.js
export let myName = "我来自test1.js";
// test2.js
export let myName = "我来自test2.js";

// index.js
import { myName as name1 } from "./test1.js";
import { myName as name2 } from "./test2.js";