一篇文章带你学会整个ES6

简介: ES 全称 EcmaScript,是脚本语言的 规范 ,而平时经常编写的 JavaScript ,是 EcmsScript 的 一种实现 ,所以 ES 新特性其实是指 JavaScript 的新特性 。

一篇文章带你学会整个ES6


ES 介绍


  • ES 全称 EcmaScript,是脚本语言的 规范 ,而平时经常编写的 JavaScript ,是 EcmsScript 的 一种实现 ,所以 ES 新特性其实是指 JavaScript 的新特性


  • 特点:
  • 语法简单,功能丰富。
  • 框架开发应用。


变量


let 变量以及声明特性


  • 语法:
let a;
let b, c, d;
let e = 100;
let f = 500, g = 'iloveyou', h = []
  • 声明特性:


  • 变量不能重复声明。
  • 块级作用域(只在代码块中才能使用)。
  • 不存在变量提升。
  • 不影响作用域链。


const 变量以及声明特性


  • 语法:
const SCHOOL = 'xxx大学'
  • 声明特性:


  • 一定要赋初始值。
  • 一般变量使用大写(潜规则)。
  • 常量的值不能修改。
  • 块级作用域。
  • 对于数组和对象的元素修改,不算做对常量的修改,不会报错。(原因:数组指向的地址值没有发生改变。)


ES 6 的变量解构赋值


  • 数组的解构
const F4 = ['小沈阳', '刘能', '赵四', '宋小宝'];
let [xiao, liu, zhao, song] = F4;
console.log(xiao)
console.log(liu)
console.log(zhao)
console.log(song)

对象的解构

const zhao = {
  name: '赵本山',
  age: '不详',
  xiaopin: function () {
    console.log("我可以演小品")
  }
}
let { name, age, xiaopin } = zhao
console.log(name)
console.log(age)
console.log(xiaopin)
xiaopin()

模板字符串


  • 语法:
let str = `我也是一个字符串`
  • 声明特性:


  • 内容中可以直接出现换行符。
  • 变量拼接。


简化对象写法


  • ES 6 允许在大括号里面 ,直接写入变量和函数,作为对象的属性和方法。
let name = 'xxx'
let change = function () {
  console,log('我可以改变你')
}
const school = {
  name, // 等价于 name: name
  change  // 等价于 change: change
  improve () {
    console.log('我们可以提高你的技能')
  }
}

函数


箭头函数以及声明特点


  • 语法:
let fn = function () {
  // 函数体
}
let fn = () => {
  // 函数体
}

特性:


  • this 是静态的,this 始终指向函数声明时所在作用域下的 this 的值。


  • 不能作为构造函数实例化对象。


  • 不能使用 arguments 变量。


  • 箭头函数简写:
// 当形参有且仅有一个的时候,可以省略括号
let add = n => {
  return n + n;
}
// 当函数体只有一条语句时,此时花括号可以省略,return 必须省略。而且语句的执行结果就是函数的返回值。
let pow = n => n * n;


函数参数的默认值


  • ES 6 允许给函数参数赋值初始值。


  • 形参初始值
// 形参初始值,具有默认值的参数,一般位置要靠后(潜规则)
function add(a, b, c=10) {
  return a + b +c
}
add(1, 2, 3)  // 6
add(1, 2) // 13

与解构赋值结合

function connect ({ host="127.0.0.1", username, password, port }) {
  console.log(host)
  console.log(username)
  console.log(password)
  console.log(port)
}
connect({
  host: 'localhost',
  username: 'root',
  password: 'root',
  port: 3306
})

ES 6 的 rest 函数


  • ES 6 引入 rest 函数,用于获取函数的实参,用来代替 arguments 。
// ES 5 获取实参的方式:
function date () {
  console.log(arguments);
}
date('阿娇', '柏芝', '思慧')
// ES 6 获取实参
function date(...args) {
  console.log(args);
}
date('阿娇', '柏芝', '思慧')

注意事项:

// rest 参数必须放到参数最后
function fn(a, b, ...args) {
  console.log(a); // 1
  console.log(b); // 2
  console.log(args);  // [3, 4, 5, 6]
}
fn(1, 2, 3, 4, 5, 6)

扩展运算符


  • ... :扩展运算符能将 数组 转换为逗号分隔的 参数序列
const tfboys = ['易烊千玺', '王源', '王俊凯']
function chunwan () {
  console.log(arguments)
}
chunwan(...tfboys) //  等价于 chunwan('易烊千玺', '王源', '王俊凯')

应用:

// 1. 数组的合并
const tfboys = ['易烊千玺', '王源', '王俊凯']
const kuiazi = ['王太利', '肖央']
const newGroup = [...kuaizi, ...tfboys]
// 2. 数组的克隆
const sanzhihua = ['E', 'G', 'M']
const sanyecao = [...sanzhihua] // 浅拷贝
// 3. 将伪数组转为真正的数组
const divs = document.querySelectorAll('div')
const divArr = [...divs]  // 此时就变成了真正的数组


数据类型


Symbol


  • ES 6 引入了一种新的原始数据类型 Symbol ,表示独一无二的值,它是 JavaScript 语言的第七种数据类型,是一种类似于字符串的数据类型。


  • 特点:


  • Symbol 的值是唯一的,用来解决命名冲突的问题。


  • Sysbol 值不能与其他数据进行运算。


  • Symbol 定义的对象属性不能使用 for...in 循环遍历,但是可以使用 Reflect.ownKeys 来获取对象的所有键名。


  • 创建 Symbol 的方式
let s = Symbol()
let s2 = Symbol('标识符1')
let s3 = Symbol('标识符1')
console.log(s2 === s3)  // false
// Symbol.for 创建
let s4 = Symbol.for('标识符2')
let s5 = Symbol.for('标识符2')
console.log(s4 === s5)  // true

对象添加 Symbol 类型的属性


  • 向对象中添加方法 up down
let game = {
  name: '俄罗斯方块',
  up: function () {},
  down: function () {}
}
// 1. 声明一个对象
let methods = {
  up: Symbol(),
  down: Symbol()
}
// 2. 将声明的对象中的 up 和 down 添加到 game 中
game[methods.up] = function () {
  console.log('我可以改变形状')
}
game[methods.down] = function () {
  console.log('我可以改变大小')
}
let youxi = {
  name: '狼人杀',
  [Symbol('say')]: funcyion () {
    console.log('我可以发言')
  },
  [Symbol('zibao')]: funcyion () {
    console.log('我可以自爆')
  }
}


Symbol 内置值


  • 除了定义自己使用的 Symbol 值以外, ES 6 还提供了 11 个内置的 Symbol 值,指向语言内部使用的方法。


迭代器


  • 迭代器(iterator)是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 itrator 接口,就可以完成遍历操作。


  • ES 6 创造了一种新的遍历命令 for...on 循环,Iterator 接口主要提供 for...on 消费。


  • 原生具有 Itrator 接口的数据(可用 for...of 遍历)。


  • Array
  • Arguments
  • Set
  • Map
  • String
  • TypedArray
  • NodeList


  • 工作原理:


  • 创建一个指针对象,指向一个当前数据结构的起始位置。
  • 第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员。
  • 接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员。
  • 每调用 next 方法返回一个包含 value 和 down 属性的对象。


  • 注意:需要自定义遍历数据的时候,要想到迭代器。


自定义遍历数据


const banji = {
  name: '终极一班',
  stus: [
    '汪大东',
    '雷婷',
    '中万钧',
    '金宝三'
  ],
  [Symbol.iterator] () {
    let index = 0
    let _this = this
    return {
      next: function() {
        if (index < _this.stus.length) {
          const result = { value: _this.stus[index], down: false }
          index++
          return result
        } else {
          return { value: undefined, down: true }
        }
      }
    }
  }
}
for (let v of banji) {
  console.log(v);
}


生成器函数声明与调用


  • 生成器就是一个特殊的函数,来进行异步编程。
function * gen(){
  console.log('111')
  yield '一只没有耳朵'  // yield: 函数代码的分隔符
  console.log('222')
  yield '一只没有耳朵'
  console.log('333')
  yield '一只没有耳朵'
  console.log('444')
}
let iterator = gen()
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
// 遍历
for(let v of gen()){
  console.log(v)
}


生成器函数的参数传递


function * gen(arg){
  console.log(arg)  // AAA
  let one = yield 111 // yield: 函数代码的分隔符
  console.log(one)  // BBB
  let two = yield 222
  console.log(two)  // CCC
  let three = yield 333
  console.log(three)  // DDD
}
let iterator = gen('AAA')
console.log(iterator.next('BBB'))
console.log(iterator.next('CCC'))
console.log(iterator.next('DDD'))


生成器函数实例


  • 回调地狱
setTimeout(() => {
  console.log(111)
  setTimeout(() => {
    console.log(222)
    setTimeout(() => {
      console.log(333)
    }, 3000)
  }, 2000)
}, 1000)

利用生成器函数解决回调地狱:

function one() {
  setTimeout(() => {
    console.log(111)
    iterator.next()
  },1000)
}
function two() {
  setTimeout(() => {
    console.log(222)
    iterator.next()
  },2000)
}
function three() {
  setTimeout(() => {
    console.log(333)
    iterator.next()
  },3000)
}
function * gen() {
  yield one()
  yield two()
  yield three()
}
// 调用生成器函数
let iterator = gen()
iterator.next()

生成器函数案例

// 获取用户数据, 订单数据, 商品数据
    function getUser() {
      setTimeout(() => {
        let data = '用户数据'
        iterator.next(data)
      }, 1000)
    }
    function getOrder() {
      setTimeout(() => {
        let data = '订单数据'
        iterator.next(data)
      }, 1000)
    }
    function getGoods() {
      setTimeout(() => {
        let data = '商品数据'
        iterator.next(data)
      }, 1000)
    }
    function* gen() {
      let user = yield getUser()
      console.log(user);
      let order = yield getOrder()
      console.log(order);
      let goods = yield getGoods()
      console.log(goods);
    }
    // 调用生成器函数
    let iterator = gen()
    iterator.next()


Promise


  • Promise 是 ES 6 引入的异步编程的新解决方案。语法上 Promise 是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果。


  • Promise 构造函数:Promise(excutor){}
  • Promise.prototype.then 方法。
  • Promise.prototype.catch 方法。
// 实例化 Promise 对象
    const p = new Promise(function(resolve, reject){
      setTimeout(function(){
        // 成功时调用 resolve
        let data = '数据库中的数据'
        resolve(data)
        // 失败时调用 reject
        let err = '数据读取失败'
        reject(err)
      }, 1000)
    })
    // 调用 Promise 对象的 then 方法
    p.then(function(value){
      console.log(value);
    }, function(reason){
      console.log(reason);
    })


Promise 封装读取文件


// 读取文件
fs.readFile(文件路径, (err, data) => {
  // 如果失败,则抛出错误
  if(err) throw err
  // 如果没有出错,则输出内容
  console.log(data.toString())
})
// 用 promise 封装读取文件
const p = new Promise(function(resolve, reject){
  fs.readFile(文件路径, (err, data)=> {
    // 判断如果失败
    if(err) reject(err)
    // 如果成功
    resolve(data)
  })
})
p.then(function(value){
  console.log(value.toString)
}, function(reason){
  console.log("读取失败!!")
})


Promise 封装 AJAX


  • 原生 AJAX:
// 1. 创建对象
const xhr = new XMLHttpRequest()
// 2. 初始化
xhr.open("GET", 接口地址)
// 3. 发送   
xhr.send()
// 4. 绑定事件,处理响应结果
xhr.onreadystatechange = function () {
  // 判断
  if (xhr.readyState === 4) {
    // 判断响应状态码 200-299
    if (xhr.status >= 200 && xhr.status < 300) {
      // 表示成功
      console.log(xhr.response);
    } else {
      console.error(xhr.status);
    }
  }
}

Promise 封装 AJAX:

// Promise 封装 AJAX
const p = new Promise((resolve, reject) => {
  const xhr = new XMLHttpRequest()
  xhr.open("GET", 接口地址)
  xhr.send()
  xhr.onreadystatechange = function () {
    if (xhr.readyState === 4) {
      if (xhr.status >= 200 && xhr.status < 300) {
        resolve(xhr.response);
      } else {
        reject(xhr.status);
      }
    }
  }
})
p.then(function(value){
  console.log(value);
}, function (reason) {
  console.log(reason);
})


Promise.prototype.then 方法


  • 调用 then 方法,then 方法的返回结果是 Promise 对象,对象状态由回调函数的执行结果决定。


  • 如果回调函数中返回的结果是 非 Promise 类型的属性,状态为成功,返回值为对象的成功的值。


Promise 实践 - 读取多个文件


  • 原生:
const fs = require('fs')
fs.readFile(文件路径, (err, data1) => {
  fs.readFile(文件路径, (err, data2) => {
    fs.readFile(文件路径, (err, data3) => {
      let result = data1 + '\r\n' + data2 + '\r\n' + data3
      console.log(result);
    })
  })
})

Promise 版:

const p = new Promise((resolve, reject) => {
  fs.readFile(文件路径, (err, data) => {
    resolve(data)
  })
})
p.then(value => {
  return new Promise((resolve, reject) => {
    fs.readFile(文件路径, (err, data) => {
      resolve([value, data])
    })
  })
}).then(value => {
  return new Promise((resolve, reject) => {
    fs.readFile(文件路径, (err, data) => {
      value.push(data)
      resolve(value)
    })
  })
}).then(value => {
  console.log(value);
})


Promise 的 catch 方法


  • 用来捕获 Promise 失败的回调函数,相当于一个语法糖。
const p = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject('出错了')
  })
})
// p.then(function(value){}, function(reason){
//   console.error(reason);
// })
p.catch(function(reason){
  console.warn(reason);
})


数据结构


Set


  • ES 6 提供了新的数据结构 Set (集合)。它类似于数组,但成员的值都是唯一的,集合实现了 iterator 接口,所以可以使用 【扩展运算符】和 【for...of...】进行遍历,集合的属性和方法:
属性或方法 说明
size 返回集合的元素个数
add 增加一个新元素,返回当前集合
delete 删除元素,返回 boolean 值
has 检测集合中是否包含某个元素,返回 Boolean 值

应用场景

// 1. 数组去重
let arr = [1,2,2,4,3,5,5,3,2,6]
let reasult = [...new Set(arr)]
// 2. 交集
let arr2 = [4,4,5,4,6,5]
let reasult = [....new Set(arr)].fifter(item => {
  let s2 = new Set(arr2)
  if (s2.has(item)) {
    return true
  } else {
    return false
  }
})
// 上面的代码可以简化为:let result = [...new Set(arr)].fifter(item => new Set(arr2).has(item))
// 3. 并集
let union = [...new Set([...arr, ...arr2])]
// 4. 差集
let diff = [...new Set(arr)].fifter(item => !(new Set(arr2).has(item)))


Map


  • ES 6 tigongle  Map 数据结构。它类似于对象,也是键值对的集合。但是“健”的范围不限于字符串,各种类型的值(包括对象)都可以当作荐。Map 也实现了 iterator 接口,所以可以使用【扩展运算符】和 【for...of...】进行遍历。Map 的属性和方法:
属性或方法 说明
size 返回 Map 的元素个数
set 增加一个新元素,返回当前 Map
get 返回键名对象的键值
has 检测 Map 中是否包含某个元素,返回 Boolean 值
clear 清空集合, 返回 undefined


class 类


  • ES 6 提供了更接近传统语言的写法,引入了 Class (类)这个概念,作为对象的模板。通过 class 关键字,可以定义类。基本上,ES 6 的 class 可以看作只是一个语法糖,它的绝大部分功能, ES 5 都可以做到,新的 class 写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。


  • 知识点:


  • class 声明类
  • constructor 定义构造函数
  • extends 继承父类
  • super 调用父级构造方法
  • static 定义静态方法和属性
  • 父类可以重写
// ES 5 语法
function Phone(brand, price) {
  this.brand = brand
  this.price = price
}
Phone.prototype.call = function () {
  console.log('我可以打电话');
}
// 实例化对象
let Huawei = new Phone('华为', 5999)
// ES 6 语法
class Shouji {
  constructor(brand, price) {
    this.brand = brand
    this.price = price
  }
  call(){
    console.log('我可以打电话');
  }
}
let onePlus = new Shouji('1+', 1999)


class 静态成员


// ES 5
function Phone(){
}
Phone.name = '手机'
Phone.change = function(){
  console.log('我可以改变世界')
}
Phone.prototype.size = '5.5inch'
let nokia = new Phone()
console.log(nokia.name) // undefined
console.log(nokia.size) // 5.5inch
// ES 6
class Phone{
  // 静态属性
  static name = '手机'
  static change(){
    console.log('我可以改变世界')
  }
}
let nokia = new Phone()
console.log(nokia.name) // undefined
console.log(Phone.name) // 手机


ES 5 利用构造函数实现继承


// ES 5 语法
function Phone(brand, price) {
  this.brand = brand
  this.price = price
}
Phone.prototype.call = function () {
  console.log('我可以打电话');
}
function SmartPhone(brand, price, color, size) {
  Phone.call(this, brand, price)
  this.color = color
  this.size = size
}
// 设置子级构造函数的原型
SmartPhone.prototype = new Phone
SmartPhone.prototype.constructor = SmartPhone
// 声明子类的方法
SmartPhone.prototype.photo = function () {
  console.log("我可以拍照");
}
SmartPhone.prototype.playGame = function () {
  console.log("我可以玩游戏");
}
const chuizi = new SmartPhone('锤子', 2499, '黑色', '5.5inch')


ES 6 的类继承


class Phone {
  constructor(brand, price) {
    this.brand = brand
    this.price = price
  }
  // 父类的成员属性
  call() {
    console.log('我可以打电话');
  }
}
class SmartPhone extends Phone {
  constructor(brand, price, color, size) {
    super(brand, price)
    this.color = color
    this.size = size
  }
  photo() {
    console.log('我可以拍照');
  }
  playGame() {
    console.log('我可以玩游戏');
  }
}
const xiaomi = new SmartPhone('小米', 799, '黑色', '4.7inch')


子类对父类方法的重写


class Phone {
  constructor(brand, price) {
    this.brand = brand
    this.price = price
  }
  // 父类的成员属性
  call() {
    console.log('我可以打电话');
  }
}
class SmartPhone extends Phone {
  constructor(brand, price, color, size) {
    super(brand, price)
    this.color = color
    this.size = size
  }
  photo() {
    console.log('我可以拍照');
  }
  playGame() {
    console.log('我可以玩游戏');
  }
  call() {
    console.log('我可以视频通话')
  }
}
const xiaomi = new SmartPhone('小米', 799, '黑色', '4.7inch')


class 中的 getter 和 setter 设置


class Phone {
  get price(){
    console.log("价格属性被读取了")
    return 'iloveyou'
  }
  set price(newVal){
    console.log("价格属性被修改了")
  }
}
// 实例化对象
let s = new Phone()
console.log(s.price); // 调用 get 方法,得到的结果是返回值 
s.price = 'free'  // 调用 set 方法


ES 6 的数值扩展


数值扩展 说明
Number.EPSILON 是 JavaScript 表示的最小精度
二进制、八进制、十进制、十六进制


Number.isFinite 检测一个数值是否为有限数
Number.isNaN 检测一个数值是否为 NaN
Number.parseInt 字符串转整数
Number.parseFloat 字符串转整数
Number.isInteger 判断一个数是否为整数
Math.trunc 将数字的小数部分抹掉
Math.sign 判断一个数到底为正数,负数还是零


ES 6 的对象扩展


对象扩展 说明
Object.is 判断两个值是否完全相等
Object.assign 对象的合并
Object.setPrototypeOf 设置原型对象
Object.getPrototypeOf



模块化


  • 模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。


模块化的好处


  • 防止命名冲突。
  • 代码复用。
  • 高维护性。


模块化规范产品


  • ES 6 之前的模块化规范:


  • CommonJS => NodeJS\Browserify
  • AMD => requireJS
  • CMD => seaJS


ES 6 模块化语法


  • 模块功能主要由两个命令构成:export 和 import 。


  • export 命令用于规定模块的对外接口。
  • import 命令用于输入其他模块提供的功能。


使用 babel 对 ES 6 模块化代码转换


  • 步骤:


  • 安装工具 babel-cli babel-preset-env browserify(webpack)
  • npx babel src/js -d dist/js
  • 打包 npx browserify dist/js/app.js -o dist/bundle.js
相关文章
|
1天前
|
存储 JavaScript 前端开发
什么是Es6,有什么特点
什么是Es6,有什么特点
10 1
|
26天前
|
前端开发
关于es6
关于es6
8 0
|
6月前
|
存储 JavaScript 前端开发
ES6
ES6
45 1
|
6月前
ES6常用知识小结
ES6常用知识小结
32 0
|
前端开发 JavaScript API
ES6(二)
es6相关知识
69 0
|
网络架构 索引
ES6(一)
- 使用let,声明的变量仅在块级作用域内有效 - var命令声明的,在全局范围内都有效 - const声明一个只读的常量。一旦声明,常量的值就不能改变。 - const的作用域与let命令相同:只在声明所在的块级作用域内有效。 - let命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错。 - let不允许在相同作用域内,重复声明同一个变量。 - 什么时候用 let,什么使用用 const——如果不知道用什么的时候,就用 const
52 0
|
JavaScript 前端开发 Java
【ES6】初识
【ES6】初识
|
JSON JavaScript 前端开发
ES5和ES6的介绍
《前端基础》
426 0
|
前端开发 JavaScript 网络架构
除了ES6,ES还有那些必须要懂得知识?
Includes 方法用来检测数组中是否包含某个元素,返回布尔类型值。
108 0
除了ES6,ES还有那些必须要懂得知识?