Es6新特性

58 阅读8分钟

1. 块级作用域: 使用{}定义块级作用域,使变量在块内有效。

特点和优势:

变量隔离:在块级作用域内声明的变量不会污染全局作用域,避免了变量命名冲突和意外的全局变量修改。

提高可读性和可维护性:可以更清晰地组织代码,将相关的变量和操作放在一起,提高代码的可读性和可维护性。

避免变量提升:在 ES5 中,变量声明会被提升到函数作用域的顶部,而在块级作用域中,变量只有在声明后才能访问,避免了一些因变量提升导致的问题。

更好的内存管理:由于变量的作用域更小,在不需要时可以更及时地被垃圾回收器回收,提高了内存管理的效率。

示例

{

  let x = 10; // 在块级作用域内声明变量 x

  console.log(x); // 可以在块内访问变量 x

}

console.log(x); // 在块外访问变量 x 会导致ReferenceError

 

2. 箭头函数:简洁的函数表达式,使用=> 定义,没有this。

特点和优势:

简洁的语法:箭头函数的语法比传统的函数表达式更简洁,减少了代码的冗余。

没有 this 绑定:箭头函数中的 this 指向的是函数定义时的上下文,而不是函数调用时的上下文。这使得箭头函数在某些情况下更容易理解和使用。

不支持 new 操作符:箭头函数不能作为构造函数使用,因为它没有 prototype 属性。

没有自己的 arguments 对象:箭头函数中没有自己的 arguments 对象,如果需要访问函数的参数,可以使用 rest 参数 或展开运算符。

隐式返回:如果箭头函数只有一个表达式作为 body,那么这个表达式的值就是函数的返回值,不需要使用 return 语句。

示例

let myFunction = () => { // 定义一个箭头函数

  console.log('Hello, World!');

};

myFunction(); // 调用箭头函数

 

3. 类和类的继承:支持面向对象编程的类语法。

特点和概念

类的定义:使用 class 关键字来定义类,类中可以包含属性和方法。

构造函数:类中默认有一个构造函数,可以在构造函数中初始化类的属性。

方法:类中可以定义方法,方法可以访问类的属性和调用其他方法。

继承:使用 extends 关键字来实现类的继承,子类可以继承父类的属性和方法,并可以重写父类的方法。

** super 关键字**:在子类的构造函数或方法中,可以使用 super 关键字来调用父类的构造函数或方法。

静态属性和方法:类可以定义静态属性和方法,静态属性和方法可以通过类名直接访问,而不需要创建类的实例。

示例:

class Person {

  constructor(name, age) {

    this.name = name;

    this.age = age;

  }

  sayHello() {

    console.log(Hello, I'm ${this.name} and I'm ${this.age} years old.);

  }

}

class Employee extends Person {

  constructor(name, age, salary) {

    super(name, age); // 调用父类的构造函数

    this.salary = salary;

  }

  calculateSalary() {

    console.log(My salary is ${this.salary} per month.);

  }

}

let person = new Person('John Doe', 30);

person.sayHello();

let employee = new Employee('Jane Doe', 40, 5000);

employee.sayHello();

employee.calculateSalary();

 

4. 增强的对象属性:如属性简写、计算属性、方法属性等。

特点:

属性简写:可以在对象的定义中直接省略属性名后面的 : 和值,例如 let obj = { name },相当于 let obj = { name: '' }。

计算属性:使用 get 和 set 方法来定义计算属性,计算属性的值可以根据其他属性的值动态计算得到。

方法属性:对象的属性值可以是一个函数,这样就可以将方法作为对象的属性来使用。

示例:

let person = {

  name: "John Doe",

  age: 30,

  sayHello: function () {

    console.log(Hello, I'm ${this.name} and I'm ${this.age} years old.);

  },

};

person.sayHello();

 

class Person {

  constructor(name, age) {

    this.name = name;

    this.age = age;

  }

 

  // 定义计算属性 fullName

  get fullName() {

    return this.name + " " + this.age;

  }

 

  // 定义 set 方法来处理 fullName 的设置

  set fullName(newFullName) {

    // 解析 newFullName 并设置 name 和 age 属性

    const nameAndAge = newFullName.split(" ");

    this.name = nameAndAge[0];

    this.age = parseInt(nameAndAge[1]);

  }

}

 

let person = new Person("John Doe", 30);

 

console.log(person.fullName);

person.fullName = "JaneDoe 40";

console.log(person.name);

console.log(person.age);

 

 

5. 模版字符串: 使用``定义包含变量和表达式的字符串。

特点

变量插值:可以在模版字符串中使用花括号 {} 来插入变量或表达式,例如 let name = 'John Doe'; let greeting = Hello, ${name}!;。

多行字符串:模版字符串可以包含多行文本,不需要使用换行符或字符串拼接,例如 let multiLineText = This is a
multiline string.;。

模板标签:模版字符串可以使用模板标签来进行逻辑处理,例如 let condition = true; let result = condition? Yes:No;。

示例

let name = 'John Doe';

let age = 30;

let greeting = Hello, ${name}! You are ${age} years old.;

 

console.log(greeting);

 

6. 解构赋值:方便地从对象或数组中提取并赋值给变量。

特点

对象解构赋值:可以使用花括号 {} 来解构对象,将对象中的属性赋值给变量,例如 let { name, age } = { name: 'John Doe', age: 30 };。

数组解构赋值:可以使用方括号 [ ] 来解构数组,将数组中的元素赋值给变量,例如 let [one, two, three] = [1, 2, 3];。

默认值:可以为解构赋值指定默认值,如果对象或数组中没有对应的属性或元素,则使用默认值,例如 let { name = 'Unknown', age = 0 } = {};。

嵌套解构:可以进行嵌套解构,将对象或数组中的嵌套对象或数组进行解构赋值,例如 let { person: { name, age } } = { person: { name: 'John Doe', age: 30 } };。

 

不完全解构:可以只解构对象或数组中的部分属性或元素,例如 let { name } = { name: 'John Doe', age: 30 };。

示例

let person = { name: 'John Doe', age: 30, city: 'New York' };

let { name, age } = person;

 

console.log(name);

console.log(age);

 

7. 迭代器和生成器:用于遍历和生成数据。

迭代器是一种可以遍历数据结构的工具。它提供了一种统一的接口,使得我们可以使用相同的方式来遍历不同的数据结构,例如数组、对象、Set、Map 等。迭代器有以下特点:

可迭代对象:一些数据结构(如数组、Set、Map 等)本身就是可迭代对象,可以直接使用迭代器进行遍历。

next 方法:通过调用迭代器的 next 方法,可以获取下一个元素。

三种状态:迭代器有三种状态:ready(准备好下一个元素)、value(当前元素)和 done(遍历结束)。

生成器是一种特殊的函数,它可以在函数执行的过程中暂停和恢复执行。生成器有以下特点:

yield 关键字:使用 yield 关键字可以在函数中暂停执行,并返回一个值。

可迭代对象:生成器函数本身就是一个可迭代对象,可以使用迭代器进行遍历。

异步操作:生成器可以用于处理异步操作,例如异步请求。

示例

// 迭代器示例

let array = [1, 2, 3, 4, 5];

let iterator = arraySymbol.iterator;

 

while (true) {

  let result = iterator.next();

  if (result.done) {

    break;

  }

  console.log(result.value);

}

 

// 生成器示例

function* generateNumbers() {

  yield 1;

  yield 2;

  yield 3;

  yield 4;

  yield 5;

}

 

let generator = generateNumbers();

for (let value of generator) {

  console.log(value);

}

 

8. 模块系统:引入了模块的概念,提高了代码的组织和复用性。

特点:

导入导出:模块可以使用 import 关键字导入其他模块的代码,使用 export 关键字导出自己的代码。

模块作用域:模块内部的代码具有独立的作用域,不会影响其他模块的代码。

模块打包:可以使用模块打包工具(如 Webpack、Rollup 等)将多个模块打包成一个文件,以便在浏览器中加载。

示例

// 模块 A

export function multiply(a, b) {

  return a * b;

}

 

// 模块 B

import { multiply } from './moduleA';

 

console.log(multiply(2, 3));

 

9. Set和Map数据结构:用于处理集合和关联数据。

Set 数据结构是一种不允许重复元素的数据结构。它可以用于存储唯一的元素,并提供了一些有用的方法,例如添加元素、删除元素、检查元素是否存在等。Set 数据结构的特点包括:

不允许重复元素:Set 中的元素必须是唯一的。

无序性:Set 中的元素没有顺序。

快速查找:Set 可以快速查找元素是否存在。

let set = new Set();

set.add(1);

set.add(2);

set.add(2); // 重复元素不会被添加到 Set 中

 

console.log(set.size); // 输出 2,因为 Set 中只有 2 个元素

 

set.delete(1);

console.log(set.has(1)); // 输出 false,因为 1 已经被删除了

 

Map 数据结构是一种键值对的数据结构,它可以用于存储关联的数据。Map 提供了一些有用的方法,例如添加键值对、获取键对应的值、删除键值对等。Map 数据结构的特点包括:

 

键值对:Map 中的每个元素都是一个键值对。

无序性:Map 中的键值对没有顺序。

快速查找:Map 可以快速根据键查找对应的值。

示例

 

let map = new Map();

map.set('name', 'John Doe');

map.set('age', 30);

map.set('city', 'New York');

 

console.log(map.get('name')); // 输出 'John Doe'

console.log(map.size); // 输出 3,因为 Map 中有 3 个键值对

 

map.delete('age');

console.log(map.has('age')); // 输出 false,因为 'age' 已经被删除了

 

10. Promise:处理异步操作的一种方式。

特点

异步操作的封装:Promise 用于封装异步操作的结果,使得异步操作可以像同步操作一样进行处理。

状态:Promise 有三种状态:pending(进行中)、fulfilled(成功)和 rejected(失败)。

回调函数:可以为 Promise 添加回调函数,以便在异步操作完成后执行相应的操作。

链式调用:Promise 支持链式调用,可以方便地组合多个异步操作。

 

示例

 

function fetchData(url) {

  return new Promise((resolve, reject) => {

    fetch(url)

     .then(response => response.json())

     .then(data => resolve(data))

     .catch(error => reject(error));

  });

}

 

fetchData('xxx')

 .then(data => console.log(data))

 .catch(error => console.error(error));

 

11. 异步/等待(async /await):更方便的编写异步代码。

async/await 的特点包括:

 

异步代码同步化:使用 async/await 可以将异步代码转换为同步代码的形式,提高代码的可读性和可维护性。

返回Promise:async 函数总是返回一个 Promise 对象。

暂停执行:当遇到 await 关键字时,异步操作会暂停执行,等待 Promise 的结果。

错误处理:如果异步操作失败,可以在 catch 语句中捕获错误。

示例


async function fetchData() {

  try {

    let response = await fetch('example.com/data');

    let data = await response.json();

    console.log(data);

  } catch (error) {

    console.error(error);

  }

}

 

fetchData();


 

12. 扩展运算符:用于展开数组和对象。

特点

展开数组:可以将一个数组展开为多个参数,例如 [1, 2, 3,...arr]。

展开对象:可以将一个对象展开为多个参数,例如 {a: 1, b: 2,...obj}。

合并数组:可以使用扩展运算符合并多个数组,例如 [...arr1,...arr2]。

替换对象的属性:可以使用扩展运算符替换对象的属性,例如 {...obj, newProp: newValue}。

示例

 

let arr1 = [1, 2, 3];

let arr2 = [4, 5, 6];

 

let mergedArr = [...arr1,...arr2];

console.log(mergedArr);

 

let obj1 = {a: 1, b: 2};

let obj2 = {c: 3, d: 4};

 

let mergedObj = {...obj1,...obj2};

console.log(mergedObj);