ES6

107 阅读6分钟

1.let和const

var的缺陷:允许重复命名,存在变量提升,没有给变量赋值时默认为undefined

let特性

  • 1、不允许重复命名
  • 2、不存在变量提升
  • 3、块级作用域 暂存死区(从块的开始到声明这段的区域)

const特性

同let,声明一个只读的常量。(一旦声明,常量的值就不能改变)

关于作用域

var的变量由函数划分作用域

let的变量由代码块划分作用域

 for (var i =0; i<3; i++){
    document.addEventListener('click',function () {
      console.log(i);   //3,3,3
    },false)

  }

可以不需要闭包,就可以解决正常显示。

 for (let i =0; i<3; i++){
    document.addEventListener('click',function () {
      console.log(i);   //0,1,2
    },false)

  }

2.箭头函数和模板字符串

箭头函数

//没有参数
() => {函数声明}

//一个参数
单一参数 => {函数声明}

//多个参数
(参数1, 参数2, …, 参数N) => { 函数声明 }

const double2 = arr.map((number) => number*2)
- 隐式返回,省略return关键字
- 继承当前上下文的 this 关键字
- 不可以使用arguments对象
- 不推荐场景(构造函数 / 一个对象的方法 / 给原型绑定方法)

模板字符串: 是增强版的字符串,用反引号(`)标识;在占位符 ${} 中写入表达式

var string01 = `User ${user.name} is not authorized to do ${user.age}.`;

3.剩余参数运算符

用 ... 表示, 主要是打包剩余。 在集合中最后一个成员前添加(将剩余变量打包为一个新的集合)

// 01- 参数列表下使用 (会打包为数组)
function sum(...numbers) {
    console.log(numbers); 
    return numbers.reduce((prev,curr) => prev + curr,0)
}

// 02- 数组解构下(会打包为数组)
let [zero, , ...rest] = arr

// 03- 对象解构下(会打包为新对象)
let {zero, ...rest} = obj

4.扩展运算符

用 ... 表示, 主要起到分散的作用。(把一个可遍历对象转为一个用逗号分隔的新的参数序列)

  • 可以用来克隆数组(或对象)
  • 可以用来连接数组(或对象,形成新的参数序列)
  • 可以在方法中使用
// (相当于深拷贝)newArr复制了arr1的元素,修改时互不影响
let arr1 = ['mary','mark','bob','lily'];
let newArr = [...arr1]; 

// 合并数组
let newArr1 = [...arr1,...arr2];
let newArr2 = [...arr1,'separate',...arr2];

// 方法中使用
let fruits = ['banana','apple','orange'];
let newFruits = ['peach','pear'];
fruits.push(...newFruits);

5.解构赋值

通过解构赋值, 可以将属性/值从对象或数组中取出, 赋值给其他变量

1)解构数组

可以预留位置,可以设置默认值,可以使用剩余参数

let arr = [1,2,3,4]
let [a,b,c] = [1,2,3]   // 等效于单独赋值

let [a,,,b] = [1,2,3,4]
let [a,b,c=100] = [1,2];
let [a, ...b] = [1, 3, 5];

2)解构对象

数组的解构,元素是按次序排列的。而对象的结构是,变量必须与属性同名,

let obj = {
   name: 'ghk',
   age: 22,
   gender: 'male'
};

let {name,gender} = obj;

3)常用

// 01 - 交换变量的值
[x, y] = [y, x]

// 02 - 函数参数的定义(匹配)
function f([x, y, z]) { ... }
f([1, 2, 3])

// 03 - 提取JSON数据
let jsonData = {
  id: 42,
  status: "OK",
  data: [867, 5309]
};

let { id, status, data } = jsonData;

// 04 - 函数参数的默认值
指定参数的默认值,避免了在函数体内部写判断
var foo = config.foo || 'upfoo'

// 05 - 输入模块的指定方法(解构赋值使得输入语句非常清晰。)
const { SourceMapConsumer, SourceNode } = require("source-map")

补充. 配合扩展运算符,可以取对象的区间值,类似数组的slice()函数

const {name, age, ...exts} = item;
let newItem = {
    ...exts,
    name: 'jer'
    }

6.字符串的扩展

includes():  返回布尔值,是否找到了参数字符串
startsWith():返回布尔值,参数字符串是否在原字符串的头部
endsWith():  返回布尔值,参数字符串是否在原字符串的尾部

7.数组的扩展

Array.from():  用于将两类对象转为真正的数组
Array.of():   用于将一组值,转换为数组

arr.includes():  返回一个布尔值,表示某个数组是否包含给定的值
arr.find():      用于找出第一个符合条件的数组成员, 并返回该成员(否则返回undefined)
arr.findIndex(): 返回第一个符合条件的数组成员的位置,否则返回-1

8.对象的扩展

// 属性的简写
// 方法的简写
const obj = {
  name,
  age,
  getName(){
    console.log(this.name);
  }
};
Object.is():      比较两个值是否严格相等
Object.assign():  用于对象的合并

Object.keys():   返回一个数组,可遍历属性的键名
Object.values(): 返回一个数组,可遍历属性的键值
Obj.hasOwnProperty(obj.prop): 返回一个布尔值,是否具有指定的属性


let obj = { foo: 'bar', baz: 42 }
Object.keys(obj)             // ["foo", "baz"]
Object.values(obj)           // ["bar", 42]
obj.hasOwnProperty('foo')    //true

9.Set 和 Map

ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。 Set 本身是一个构造函数,用来生成 Set 数据结构。

01- 数组去重
先去重,再用结构赋值,转换为数组格式
let array = [1,2,3,3,3,5]
let nArray = [...new Set(array)]  // [1,2,3,5]
02- 实现并集、交集和差集
let a = new Set([1, 2, 3]);
let b = new Set([4, 3, 2]);

// 并集
let union = new Set([...a, ...b]);
console.log(...union)

// 交集
let intersect = new Set([...a].filter(x => b.has(x)));
console.log(...intersect)

// 差集
let difference = new Set([...union].filter(x => !intersect.has(x)));
console.log(...difference)

10.async函数

1.async函数返回一个 Promise 对象
2.async函数的return返回值,会成为then回调的参数
3.async函数内部抛出错误,会返回reject状态。被catch方法接收(await最好放在try...catch代码块中)
async function myFunction() {
      try {
        await somethingThatReturnsAPromise()
      } catch (err) {
        console.log(err)
      }
}

myFunction().then(function(data){
    console.log(data); 
})

多个await命令,可同时触发

// 写法一
let [foo, bar] = await Promise.all([getFoo(), getBar()])

// 写法二
let fooPromise = getFoo()
let barPromise = getBar()
let foo = await fooPromise
let bar = await barPromise

11.类和对象

1)传统方式,通过构造函数定义一个类

2)ES6引入了Class,作为对象的模板

class Person{
    constructor(myName, myAge){
        this.name = myName;
        this.age = myAge;
    }
    // 定义实例方法
    say(){
        console.log(this.name, this.age);
    }
    // 定义静态方法
    static run() {
        console.log("run");
    }
}
let p = new Person("zs", 18); //创建一个Person实例
p.say();      //调用实例方法
Person.run(); //调用静态方法
01- constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。
一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认添加。
 
02- 类里面定义方法
static关键字表示定义静态方法,实例方法写在constructor外面,默认是添加到原型上面的

12.Module

1)AMD 和 CMD
require.js遵循AMD规范,SeaJS遵循CMD规范

2)CommonJS
CommonJS是服务端模块的规范,NodeJS采用了这个规范。 CommonJS规范同步加载模块,也就是:只有加载完成,才能执行后面的操作。

3)ES6模块化:export和import

模块将代码分割为可重用的单元,模块中的(类、方法、变量)可以供外部使用,或只在模块内使用。

a)export default命令,为模块指定默认输出

export default function () {
  console.log('foo');
}

import命令可以为该匿名函数指定任意名字,不需要知道原模块输出的函数名。

import { marketing } from '../../../assets/js/api/stdmis'

b)import或export 可以使用as关键字,将输入的变量重命名

export { default as misTable } from '@/components/mis_table'