# ES

# 参考文档

# let 和 const 命令

# let 命令

  • let 声明的变量只在声明位置的域内有效,不存在变量提升。
  • let 暂时性死区。
  • let 禁止重复声明。
  • let 有块级作用域。

# 块级作用域

  • ES6 加入的

# const 命令

  • const 声明一个只读的常量。一旦声明,常量的值就不能改变。
  • const 一旦声明变量,就必须立即初始化,不能留到以后赋值。
  • 不存在变量提升。
  • 不可重复声明。
  • 常量的实质是一个存储地址的指针,它的不可变其实指的是这个地址不可以变。

# 变量的解构赋值

ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。

# 数组的解构赋值

实例:

let a = 1;
let b = 2;
let c = 3;
// 等同于下面这种写法
let [a, b, c] = [1, 2, 3];
1
2
3
4
5
  • 如果解构不成功,变量的值就等于 undefined

  • 解构赋值允许指定默认值。

    实例:

    let [foo = true] = [];
    foo // true
    
    let [x, y = 'b'] = ['a']; // x='a', y='b'
    let [x, y = 'b'] = ['a', undefined]; // x='a', y='b'
    
    1
    2
    3
    4
    5

    注意,ES6 内部使用严格相等运算符(===),判断一个位置是否有值。所以,只有当一个数组成员严格等于 undefined,默认值才会生效。

    let [x = 1] = [undefined];
    x // 1
    
    let [x = 1] = [null];
    x // null
    
    1
    2
    3
    4
    5

    如果一个数组成员是 null,默认值就不会生效,因为 null 不严格等于 undefined

  • 支持不完全解构。

# 对象的解构赋值

  • 对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。

  • 如果解构失败,变量的值等于 undefined

  • 实例:

    let {foo} = {bar: 'baz'};
    foo // undefined
    
    1
    2

    上面代码中,等号右边的对象没有 foo 属性,所以变量 foo 取不到值,所以等于 undefined。

# 字符串的扩展

# 字符串的新增方法

  • includes():返回布尔值,表示是否找到了参数字符串。

  • startsWith():返回布尔值,表示参数字符串是否在原字符串的头部。

  • endsWith():返回布尔值,表示参数字符串是否在原字符串的尾部。

  • repeat():返回一个新字符串,表示将原字符串重复 n 次。

  • trimStart(),去除头部空格。

  • trimEnd(),去除尾部空格。

  • padStart() 用于头部补全。

  • padEnd() 用于尾部补全。

  • 实例:

    'x'.padStart(5, 'ab') // 'ababx'
    'x'.padStart(4, 'ab') // 'abax'
    
    'x'.padEnd(5, 'ab') // 'xabab'
    'x'.padEnd(4, 'ab') // 'xaba'
    
    1
    2
    3
    4
    5

    padStart()padEnd() 一共接受两个参数,第一个参数是字符串补全生效的最大长度,第二个参数是用来补全的字符串。

# 函数的扩展

# 默认值

  • 实例

    function Point(x = 0, y = 0) {
      this.x = x;
      this.y = y;
    }
    
    const p = new Point();
    p // { x: 0, y: 0 }
    
    1
    2
    3
    4
    5
    6
    7

# rest 参数

  • 格式 ...变量名
  • rest 参数之后不能再有其他参数(即只能是最后一个参数),否则会报错。
  • 函数的 length 属性,不包括 rest 参数。
  • 实例:
    function add(...values) {
      let sum = 0;

      for (var val of values) {
           sum += val;
       }

      return sum;
      }

    add(2, 5, 3) // 10
1
2
3
4
5
6
7
8
9
10
11

# 箭头函数

  • 格式:

    var f = () => 5;
    // 等同于
    var f = function () { return 5 };
    
    var sum = (num1, num2) => num1 + num2;
    // 等同于
    var sum = function(num1, num2) {
    return num1 + num2;
    };
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
  • 当返回值是一个对象的时候,需要将代码块用圆括号包起来。

    由于大括号被解释为代码块,所以如果箭头函数直接返回一个对象,必须在对象外面加上括号,否则会报错。

    示例:

    // 报错
    let getTempItem = id => { id: id, name: "Temp" };
    
    // 不报错
    let getTempItem = id => ({ id: id, name: "Temp" });
    
    1
    2
    3
    4
    5
  • 使用 this 的时候不使用箭头函数,因为它会将 this 指向全局变量。

# 数组的扩展

# 扩展运算符

  • 格式:... 三个点
  • 具有 Iterator 接口的对象,都可以使用扩展运算符,将它转换成真正的数组。

# includes 方法

  • Array.prototype.includes 方法返回一个布尔值,表示某个数组是否包含给定的值,

# 对象的扩展

# 对象的新增方法

# assign 方法

  • Object.assign() 方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。

  • 注意,如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。

  • 实例:

    const target = { a: 1, b: 1 };
    
    const source1 = { b: 2, c: 2 };
    const source2 = { c: 3 };
    
    Object.assign(target, source1, source2);
    target // {a:1, b:2, c:3}
    
    1
    2
    3
    4
    5
    6
    7
  • 如果只有一个参数,Object.assign() 会直接返回该参数。

  • 浅拷贝。

# Set 和 Map 数据结构

# Map

  • size

  • set(k, v)

  • get(k)

  • has(k)

  • delete(k)

  • clear(),清除所有成员,没有返回值。

  • 新建 Map 实例时,就指定了两个键 nametitle

  • 如果对同一个键多次赋值,后面的值将覆盖前面的值。

  • 实例:

    const m = new Map();
    const o = {p: 'Hello World'};
    
    m.set(o, 'content')
    m.get(o) // "content"
    
    m.has(o) // true
    m.delete(o) // true
    m.has(o) // false
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
  • 遍历方法

  • for ... of 实例:

    const map = new Map([
      ['F', 'no'],
      ['T',  'yes'],
      ]);
    
    for (let key of map.keys()) {
      console.log(key);
    }
    // "F"
    // "T"
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

# Promise 对象

# 三个状态

Promise 对象代表一个异步操作,有三种状态:

  • pending(进行中)
  • fulfilled(已成功)
  • rejected(已失败)
  • 一旦状态改变,就不会再变,任何时候都可以得到这个结果。

# 两个参数

Promise构造函数接受一个函数作为参数。

该函数的两个参数分别是:

  • resolve
    • 将 Promise 对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved)。
    • 在异步操作成功时调用,并将异步操作的结果,作为参数传递出去。
  • reject
    • 将 Promise 对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected)。
    • 在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

它们是两个函数,由 JavaScript 引擎提供,不用自己部署。

# 方法

  • finally(),用于指定不管 Promise 对象最后状态如何,都会执行的操作。
  • all(),用于将多个 Promise 实例,包装成一个新的 Promise 实例。
    • 实例:

      const p = Promise.all([p1, p2, p3]);
      
      1
    • p 的状态由 p1、p2、p3 决定,分成两种情况。

    • 都成功才成功,只有 p1、p2、p3 的状态都变成fulfilled,p 的状态才会变成 fulfilled,此时 p1、p2、p3 的返回值组成一个数组,传递给 p 的回调函数。

    • 一个失败即失败,只要 p1、p2、p3 之中有一个被 rejected,p 的状态就变成 rejected,此时第一个被 reject 的实例的返回值,会传递给 p 的回调函数。

  • race()谁先就是谁,只要 p1、p2、p3 之中有一个实例率先改变状态,p 的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给 p 的回调函数。
    • 实例:

      const p = Promise.race([p1, p2, p3]);
      
      1

# Iterator 和 for...of 循环

# async 函数

async 函数返回一个 Promise 对象,可以使用 then 方法添加回调函数。当函数执行的时候,一旦遇到 await 就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。

# 语法

  • 返回一个 Promise 对象。

  • async 函数内部 return 语句返回的值,会成为 then 方法回调函数的参数。

    async function f() {
    return 'hello world';
    }
    
    f().then(v => console.log(v))
    // "hello world"
    
    1
    2
    3
    4
    5
    6
  • 实例:

    async function getTitle(url) {
    let response = await fetch(url);
    let html = await response.text();
    return html.match(/<title>([\s\S]+)<\/title>/i)[1];
    }
    getTitle('https://tc39.github.io/ecma262/').then(console.log)
    // "ECMAScript 2017 Language Specification"
    
    1
    2
    3
    4
    5
    6
    7

    上面代码中,函数 getTitle 内部有三个操作:抓取网页、取出文本、匹配页面标题。只有这三个操作全部完成,才会执行 then 方法里面的 console.log

# await 命令

await 命令后面是一个 Promise 对象,返回该对象的结果。如果不是 Promise 对象,就直接返回对应的值。

# Class 基本语法

  • 实例:

    // ES 5
    function Point(x, y) {
      this.x = x;
      this.y = y;
    }
    
    Point.prototype.toString = function () {
      return '(' + this.x + ', ' + this.y + ')';
    };
    
    var p = new Point(1, 2);
    // ES 6
    class Point {
    constructor(x, y) {
      this.x = x;
      this.y = y;
    }
    
    toString() {
      return '(' + this.x + ', ' + this.y + ')';
    }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22

# Class 继承

# Module 语法

# export

格式:

// 第一种
export var firstName = 'Michael';
export var lastName = 'Jackson';
export var year = 1958;
// 第二种
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958;

export { firstName, lastName, year };
1
2
3
4
5
6
7
8
9
10
// 这是方法的导出
// 报错
function f() {}
export f;

// 正确
export function f() {};

// 正确
function f() {}
export {f};
1
2
3
4
5
6
7
8
9
10
11

# import

import 命令输入的变量都是只读的,因为它的本质是输入接口。也就是说,不允许在加载模块的脚本里面,改写接口。

格式:

import { firstName, lastName, year } from './profile.js';
1

# export default

格式:

// 区别
// 第一组
export default function crc32() { // 输出
  // ...
}

import crc32 from 'crc32'; // 输入

// 第二组
export function crc32() { // 输出
  // ...
};

import {crc32} from 'crc32'; // 输入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 讨论区

由于评论过多会影响页面最下方的导航,故将评论区做默认折叠处理。

点击查看评论区内容,渴望您的宝贵建议~
Last Updated: 6/10/2022, 3:54:48 PM