JavaScript 笔记1 ES6 新特性 | 解构赋值、模板字符串、Symbol数据类型、Promise、模块化

文章目录

  • 1. ECMAScript
  • 2. ES6
  • 3. let 、const
  • 4. 解构赋值
  • 5. 模板字符串
  • 6. 对象的简化写法
  • 7. 箭头函数
  • 8. 函数参数初始值
  • 9. REST 参数
  • 10. 拓展运算符
  • 11. Symbol 数据类型
    • 11.1 Symbol 类型的特点
    • 11.2 Symbol 类型的基本使用
    • 11.3 Symbol 内置属性
  • 12. 迭代器
    • 12.1 自定义迭代器
  • 13. 生成器
    • 13.1 生成器函数的参数传递
    • 13.2 生成器实例
  • 14. Promise
    • 14.1 使用 Promise 封装 AJAX 请求
  • 15. Set
  • 16. Map
  • 17. Class
    • 17.1 Class 基本使用
    • 17.2 对象继承
    • 17.3 子类重写父类方法
    • 17.4 get 和 set
  • 18. ES6 Number 类型拓展
  • 19. ES6 对象方法的拓展
  • 20. ES6 模块化
    • 20.1 import 时使用解构赋值
    • 20.2 默认export的导入
    • 20.3 import 引入的第二种方式
    • 20.4 ES6 模块化代码转换

参考资料:

  • https://es6.ruanyifeng.com/#docs/intro
  • https://www.bilibili.com/video/BV1uK411H7on

1. ECMAScript

ECMA(European Computer Manufacturers Association)中文名称为欧洲计算机制造商协会,这个组织目标是评估、开发和认可电信和计算机标准。1994年该组织改名为 Ecma 国际。

ECMAScript 简称 ES,是脚本语言的规范,平时编写的 JavaScript,是 ECMAScript规范的一种实现,ES 新特性指的是 JavaScript 新特性

ECMAScript 是由 Ecma 国际通过 ECMA-262 标准化的脚本程序设计语言,发展历史如下:
(ECMA-262 是 Ecma国际制定了许多标准中的一个)

ECMA版本 发布日期 新特性
1 1997 年 制定了语言的基本语法
2 1998 年 较小改动
3 1999 年 引入正则、异常处理,格式化输出等,IE浏览器开始支持
4 2007年 未发布
5 2009年 引入严格模式,JSON、扩展对象、数组、原型、字符串、日期方法
6 2015年 模块化,面向对象语法、Promise、箭头函数、let、const、数组解构赋值等等
7 2016年 幂运算符、数组扩展、Async/await 关键字
8 2017年 Async/await 、字符串扩展
9 2018年 对象解构赋值,正则扩展
10 2019年 扩展对象、数组方法

注:从 ES6 开始,每年发布一个版本,版本号比年份最后一位大1

TC39 (Technical Committee 39)是推进 ECMAScript 发展的委员会,其会员都是各种公司(主要是浏览器厂商,有苹果、谷歌、微软等)。
TC39 会定期召开会议,会议由会员公司的代表与特邀专家出席

2. ES6

为什么要学习 ES6

  • ES6 的版本变动内容最多,具有里程碑意义
  • ES6 加入许多新的语法特性,编程实现更简单、高效
  • ES6 是前端发展趋势,就业必备技能

ES6与不同浏览器版本的兼容性查询
http://kangax.github.io/compat-table/es6/
JavaScript 笔记1 ES6 新特性 | 解构赋值、模板字符串、Symbol数据类型、Promise、模块化_第1张图片

3. let 、const

let 是 ES6 新推出的数据类型,let 用于声明变量,若不赋值,则默认为 undefined 类型

  1. 变量不能重复声明
  2. 块级作用域,相当于局部变量
{
   let name = 'uni' 
}
console.log(name)	// 报错, 无法访问

这里包括但不限于 if、else、while、for 、funtion 所包含的 { }

  1. 不存在变量提升,不允许在变量声明前就去使用
  2. 不影响作用域链,所在作用域的内部函数可以访问到变量
let name = 'uni';
function fn(){
   console.log(name); 
}
fn();

const 用于声明常量

  1. 在定义时必须赋值初始值
  2. 一般常量使用大写
  3. 常量的值不能修改
  4. 块级作用域
{
   const NAME = 'uni' 
}
console.log(NAME)	// 报错
  1. 支持对数组类型修改
const users = []
users.puth('uni')

4. 解构赋值

解构赋值:ES6 允许按照一定模式从数组和对象中提取值,对变量进行赋值
解构赋值一般分为数组和对象这两种
【例】对数组进行解构赋值

const words = ['a', 'b', 'c']
let [a, b, c] = words
// a = 'a'
// b = 'b'
// c = 'c'

【例】对对象进行解构赋值

const user={
   id: 1,
   name: 'uni',
   say: function(){
      console.log(`name: ${name}, id: ${id}`)
   }
}
let {id, name, say} = user;
say()

5. 模板字符串

使用 反引号,支持使用 ${} 取值,例:

let name = 'uni'
console.log(`name: ${name}`)

6. 对象的简化写法

ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法

let name = 'uni'
let say = function(){
   console.log(`name: ${uni}`)
}
const uni = {name, say}
// 相当于: const uni = {name: name, say: say}
console.log(uni)

7. 箭头函数

ES6 允许使用 =>箭头 定义函数
【例】定义求和函数

let fn = (a, b) => { return a + b } 

箭头函数的特性:

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

【例】直接调用两种定义方式的函数

function getName(){
    console.log(this.name)
}
function getName2(){
    console.log(this.name); 
}
window.name = 'uni',
const school = {
   name: 'UNI' 
}
console.log(getName())
console.log(getName2())

运行结果
uni
uni

例,使用 call 来改变函数的this

getName.call(school)
getName2.call(school)

运行结果
UNI
UNI

  1. 不能作为构造实例化对象

【例】箭头函数的错误使用

let Person = (name, age) => {
  this.name = name
  this.age = age
}
let uni = new Person('uni', 22)
console.log(uni)		// 报错
  1. 不能使用 arguments 变量
let fn = () => {
  console.log(arguments);
}
  1. 箭头函数可简写
  • 当形参只有一个时可省略小括号

简写前

let abs = (a) => {
  if(a < 0)
    return -a;
  else 
    return a;
}

简写后

let abs = a => {
  if(a < 0)
    return -a;
  else 
    return a;
}
  • 省略花括号,当代码只有一条语句时,此时的 return 必须省略,语句执行结果即为函数返回值
// 简写前
let pow = (n) => {
   return n * n 
}
// 简写后
let pow2 = n => n * n
console.log(pow(1)

使用场景:

  1. 适合与 this 无关的回调,例如定时器,数组的方法等回调
  2. 不适合与 this 有关的回调,事件回调

8. 函数参数初始值

ES6 允许给函数参数赋值默认值,经常与解构赋值结合使用
【例】

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

9. REST 参数

ES6 引入 REST 参数,用于获取函数的实参,用于代替 arguments

// ES5 获取实参的方式
function data(){
  console.log(arguments);
}
data(1,2,3)

// ES6 使用 rest 参数
function data(...args){
   console.log(args) 
}
data(1,2,3)

rest 参数必须要放到参数最后

10. 拓展运算符

ES6 的扩展运算符能将数组转换为逗号分隔的参数序列

const words = ['a', 'b', 'c']

function data(...args){
  console.log(args)  
}
data(...words)

11. Symbol 数据类型

11.1 Symbol 类型的特点

ES6 引入了一种新的基本数据类型 (第八种)Symbol,表示独一无二的值,类似于字符串。
Symbol 数据的类型的特点有:

  1. Symbol 的值是唯一的,用来解决命名冲突的问题
  2. Symbol 值不能与其他数据进行运算
  3. Symbol 定义的对象属性不能使用 for…in 循环遍历,但是可以使用 Reflect.ownKeys 来获取对象的所有键名

11.2 Symbol 类型的基本使用

// 1. 创建 Symbol
let s1 = Symbol();
console.log(s1, typeof s1) // Symbol() "symbol"
let s2 = Symbol('uni')
let s3 = Symbol('uni')
console.log(s2 == s3) 	// false

Symbol.for(key) 方法会根据给定的键 key,来从运行时的 symbol 注册表中找到对应的 symbol,如果找到了,则返回它,否则,新建一个与该键关联的 symbol,并放入全局 symbol 注册表中。
【例】

let s4 = Symbol.for('hello')
let s5 = Symbol.for('hello')
console.log(s4 === s5) // true

Symbol 可用于表示对象唯一的属性,例如:

let methods = {
   say1: Symbol(),
   say2: Symbol()
}
let game = {}
game[methods.say1] = function(){ console.log('say1'); }
game[methods.say2] = function(){ console.log('say2'); }

game[methods.say1]()

除了上述这种方法,先定义包含 Symbol() 属性的对象外,还有更简化的方法,直接在定义方法时创建 Symbol 对象,例如:


let game = {
  [Symbol('say1')]: function(){ console.log('say1'); },
  [Symbol('say2')]: function(){ console.log('say2'); }
}
// 这里的 Symbol('say1') 无法调用,通常是使用 Symbol 的内置属性来代替

11.3 Symbol 内置属性

除了定义自己使用的 Symbol 值意外, ES6 还提供了 11个内置的 Symbol 值,指向语言内部使用的方法,等用到的时候可以查看文档
参考资料:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Symbol
在 Symbol 的这些内置属性中,比较关键的就是 iterator 迭代器
Symbol.iterator 为每一个对象定义了默认的迭代器。该迭代器可以被 for…of 循环使用。

12. 迭代器

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

  1. ES6 创造了一种新的遍历命令 for … of 循环, iterator 接口主要供 for… of 消费
  2. 原生具备了 iterator 接口的数据(可用 for of 遍历)
  • Array
  • Arguments
  • Set
  • Map
  • String
  • TypeArray
  • NodeList
  1. 工作原理
  • 创建一个指针对象,指向当前数据结构的起始位置
  • 第一次调用对象的 next 方法,指针一直往后移动,直到指向最后一个成员
  • 接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员
  • 每当调用 next() 方法,就会返回一个包含 value 和 done 属性的对象

【例】

const words = ['a', 'b', 'c']

for(let word of words){
   console.log(word) 
}
// a
// b
// c

通过输出一个空的数组,我们可以观察到其原型对象支持迭代遍历的实现对象

console.log(new Array())

运行的部分结果:
在这里插入图片描述

可以看到在 Array 类型数据的 prototype 原型对象中,包含了 Symbol 类型的属性名,其值为一个 values() 函数
【例】遍历数组的迭代器

a = [1,2,3]

let iterator = a[Symbol.iterator]()
// 调用对象的 next
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())

运行结果:
JavaScript 笔记1 ES6 新特性 | 解构赋值、模板字符串、Symbol数据类型、Promise、模块化_第2张图片

12.1 自定义迭代器

自定义迭代器分为两步,1)声明 Symbol.iterator 属性,值为 一个函数,2)该函数需返回 next()方法
【例】实现只遍历长度 >= 2 的字符串数据,其他则为 undefined

const users = {
  data: ['aa', 'bb', 'cc', 'A', '1', 'DD'],
  [Symbol.iterator](){
     // 索引变量
     let index = 0
     let _this = this
     return {
        next: function(){
            if(index >= _this.data.length) 	// 若索引不合理, 则迭代结束
              return { value: undefined, done: true }
          
            if(_this.data[index].length >= 2)
               return { value: _this.data[index++], done: false }
            else{
               index++
               return { value: undefined, done: false }
            }
            
        }
     }
  }
}
for (let u of users){ 
  console.log(u)
}

13. 生成器

生成器函数是 ES6 提供的一种异步编程的解决方案,语法行为与传统函数完全不同,例:

function * gen(){
  console.log(1);
  yield '1';	// 类似于断点
  
  console.log(2);
  yield '2';
  
  console.log(3);
  yield '3';
  
}
let iterator = gen();
iterator.next();
iterator.next();
iterator.next();

13.1 生成器函数的参数传递

调用 生成器函数的 next()方法时,方法里传递的参数会作为函数执行 yield 方法后的返回值

function * gen(arg){
  console.log(arg);
  let aaa = yield 1
  console.log(aaa)
  let bbb = yield 2
  console.log(bbb)
  let ccc = yield 3
  console.log(ccc)
}
let iterator = gen('hi')
console.log(iterator.next('aaa'))
console.log(iterator.next('bbb'))
console.log(iterator.next('ccc'))

运行结果:
JavaScript 笔记1 ES6 新特性 | 解构赋值、模板字符串、Symbol数据类型、Promise、模块化_第3张图片

13.2 生成器实例

了解回调地狱 callback hell

参考资料:http://callbackhell.com/
回调:使用 JavaScript 函数的约定的名称,通常在执行 I/O时实行,例如下载文件,读取文件,数据库连接等。

回调通常发生在 异步 async 操作中,异步是指多个操作同时进行,常见的有 setTimeout 延时函数 和 AJAX 发送请求等

回调地狱:回调函数中又嵌套了一个或多个回调,例:在3秒内分别输出3, 2,1

setTimeout(() => {
  console.log(3)
  setTimeout(() => {
     console.log(2) 
     setTimeout(() => {
        console.log(1) 
     }, 1000)
  }, 1000)
}, 1000)

使用生成器函数可以解决回调地狱的问题:

function one(){
  setTimeout(() => {
    console.log(1)
  }, 3000)
}

function two(){
   setTimeout(() => {
     console.log(2) 
   }, 2000)
}

function three(){
    setTimeout(() => {
      console.log(3) 
    }, 1000)
}

function * gen(){
  yield three();
  yield two();
  yield one();
}
let iterator = gen()
iterator.next()
iterator.next()
iterator.next()

返回值具有关联的回调地狱如何解决呢?比如要先后获取用户数据、订单数据和商品数据

function getUsers(){
  setTimeout(() => {
    let data = '用户数据'
    iterator.next(data)
  }, 3000)
}

function getOrders(){
   setTimeout(() => {
     let data = '订单数据'
     iterator.next(data)
   }, 2000)
}

function getGoods(){
    setTimeout(() => {
      let data = '商品数据'
      iterator.next(data)
    }, 1000)
}

function * gen(){
  let users = yield getUsers();
  console.log(users)
  let orders = yield getOrders();
  console.log(orders)
  let goods = yield getGoods();
  console.log(goods)
}
let iterator = gen()
iterator.next()

14. Promise

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

  1. Promise 构造函数:Promise(excutor) { }
  2. Promise.prototype.then 方法
  3. Promise.prototype.catch 方法

promise 译为 承诺,里面主要有 resolve 决定 和 reject 拒绝 这两个行为

// 定义 Promise
const p = new Promise(function(resolve, reject){
    if(...)
      reject(a)
    else
      resolve(b)
}

// 使用 Promise
p.then(
   (a) => {},
   (b) => {}
).catch(error => {}) 	// 捕获异常

14.1 使用 Promise 封装 AJAX 请求

需要node环境,使用node命令执行下方的 JS代码
原生的 AJAX 异步请求实现


var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;
// 该 API 接口可以随机返回一条诗句
const url = 'https://api.apiopen.top/api/sentences'
// 1. 创建对象
const xhr = new XMLHttpRequest();
// 2. 初始化
xhr.open("GET", url)
// 3. 发送
xhr.send()
// 4. 绑定事件,处理响应结果
xhr.onreadystatechange = function(){
   if(xhr.readyState === 4){
      // 判断状态响应码
      if(xhr.status >= 200 && xhr.status < 300){  // 成功
         console.log(xhr.responseText) 
      } else{																			// 失败
         console.error(xhr.status)
      }
   }
}

运行结果
{“code”:200,“message”:“成功!”,“result”:{“name”:“河海不择细流,故能就其深
;”,“from”:“李斯《谏逐客书》”}}

使用 Promise 封装原生的 AJAX 请求


var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

// 定义 Promise
const p = new Promise((resolve, reject) => {
    const url = 'https://api.apiopen.top/api/sentences'
    // 1. 创建对象
    const xhr = new XMLHttpRequest();
    // 2. 初始化
    xhr.open("GET", url)
    // 3. 发送
    xhr.send()
    // 4. 绑定事件,处理响应结果
    xhr.onreadystatechange = function(){
        if(xhr.readyState === 4){
            // 判断状态响应码
            if(xhr.status >= 200 && xhr.status < 300){  // 成功
                resolve(xhr.responseText) 
            } else{																			// 失败
                reject(xhr.status)
            }
        }
    }
})
// 调用 Promise
p.then(
    (result) => {
        console.log('请求成功', result)
    },
    (reason) => {
        console.log('请求失败', reason)
    }
).catch((error) => {
    console.error('程序出错', error)
})

15. Set

ES6 提供了新的数据结构 Set(集合),类似于数组,其内部的值都是唯一的。
Set 集合实现了 iterator 接口,所以可使用 for…of 进行遍历
集合的属性和方法:

  1. size,返回集合的元素个数
  2. add,增加一个新元素,返回当前集合
  3. delete,删除元素,返回 boolean 的值
  4. has,检测集合中是否包含某个元素,返回 boolean 的值
  5. clear,清空集合

【例1】使用 Set 去重

let arr = [1,1,2,2,2,3,3]
let result = [...new Set(arr )];
console.log(result);

【例2】 使用 Set 求两个数组的交集

let arr1 = [1,1,2,2,2,3,3]
let arr2 = [3,3,2]
let result = [...new Set(arr1)].filter(
    item => {
        let a2 = new Set(arr2)
        if(a2.has(item))
            return true
        else 
            return false
    }
)
console.log(result)

简化写法

let result = [...new Set(arr1)].filter(item => new Set(arr2).has(item)); 

【例3】 使用 Set 求两个数组的并集

let arr1 = [1,1,2,2,2,3,3]
let arr2 = [3,3,2]
let result = [...new Set([...arr1, ...arr2])]
console.log(result)

【例4】使用 Set 求两个数组的差集

let arr1 = [1,1,2,2,2,3,3]
let arr2 = [3,3,2]

let diff = [...new Set(arr1)].filter(item => !(new Set(arr2).has(item)))
console.log(diff)

16. Map

ES6 提供了 Map 数据结构,类似于 Object,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当做键。Map也实现了 iterator 接口,所以可以使用 for…of 进行遍历,Map 的常用方法有:

  1. size,返回 Map 的元素个数
  2. set,增加新元素,返回当前的 Map
  3. get,返回指定键的值
  4. has,检测 Map 中是否包含某个元素,返回结果为 boolean 类型
  5. clear,清空集合,返回 undefined
map = new Map()
map.set('name', 'uni')
map.set('age', 22)

for(let node of map){
    console.log('key=',node[0], ',value=',node[1])
}

17. Class

ES6 引入了 Class 类的概念,作为对象的模板,通过 class 关键字可以定义类。基本上,ES6 的 class 可以看做一个语法糖,它的绝大部分功能, ES5 都可以做到,新的 class 写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
知识点:

  1. class 声明类
  2. constructor 定义构造函数初始化
  3. extends 继承父类
  4. super 调用父类构造方法
  5. static 定义静态方法和属性
  6. 父类方法可以重写

17.1 Class 基本使用

【例】面向对象编程(ES5的写法)

function User(name, age){
    this.name = name;
    this.age = age
}
// 给类添加方法
User.prototype.sayHello = function(){
    console.log(`My name is ${this.name}, age is ${this.age}`)
}
// 实例化对象
let Uni = new User('Uni', 22)
// 调用对象的方法
Uni.sayHello()

运行结果
My name is Uni, age is 22

ES6的写法

class User{
   // 构造方法
    constructor(name, age){
       this.name = name;
       this.age = age; 
    }
    // ES6 Class类里的方法必须使用方法名() ,而不能使用 ES5的 方法名:function()
    sayHello(){
        console.log(`My name is ${this.name}, age is ${this.age}`)
    }
}
let Uni = new User('Uni', 22)
Uni.sayHello()

ES6 的 Class 支持静态属性,使用 static 关键字定义

class User{
    // 静态属性
    static body = 'normal'
    // 构造方法
     constructor(){}
 }

17.2 对象继承

【例】面向对象编程实现手机类 (ES5写法)

// 定义父类手机
function Phone(brand, price){
    this.brand = brand
    this.price = price
}
// 定义方法
Phone.prototype.call = function(){
    console.log('打电话')
}
// 定义子类
function SmartPhone(brand, price, color, size){
    // 调用父类的构造方法并修改父类的 this 指向
    Phone.call(this, brand, price)
    this.color = color
    this.size = size
}
//设置子级构造函数的原型
SmartPhone.prototype = new Phone
SmartPhone.prototype.constructor = SmartPhone

// 声明子类的方法
SmartPhone.prototype.phone = function(){
    console.log('拍照')
}
const HuaWei = new SmartPhone('华为', 3099, '黑色', '5.5英寸')
console.log(HuaWei)

运行结果
SmartPhone { brand: ‘华为’, price: 3099, color: ‘黑色’, size: ‘5.5英寸’ }

使用 ES6 实现上述案例:

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) // 相当于 Phone.call(this, brand, price)
        this.color = color
        this.size = size
    }
    photo(){ console.log('拍照') }
}

const HuaWei = new SmartPhone('华为', 3099, '黑色', '5.5英寸')
console.log(HuaWei)

17.3 子类重写父类方法

class A{
    constructor(){}
    hello(){ console.log('A: hello')}
}
class B extends A {
    constructor(){super()}
    hello() { 
        // 重写方法时可调用父类的方法
        super.hello(); 
        console.log('B: hello')}
}
b = new B()
b.hello()

17.4 get 和 set

【例】

class Phone{
    // constructor 构造函数可以不写
    get price(){            // 默认返回当前属性值
       console.log('价格属性被读取')
       return this.p
    }
    set price(val){
        console.log('价格属性被修改')
        this.p = val
    }
}
let phone = new Phone()

console.log(phone.price) // undefined

phone.price = 100

console.log(phone.price)

运行结果
价格属性被读取
undefined
价格属性被修改
价格属性被读取
100

18. ES6 Number 类型拓展

Number.EPSILON 可以表示最小精度,用于浮点数之间的运算,当两个数的差值小于这个精度时候,则视为相等,默认值为 2.220446049250313e-16

0b 可表示二进制,0o表示八进制,0x表示十六进制

console.log(0b1010)
console.log(0o12)
console.log(10)
console.log(0xA)

运行结果
10
10
10
10

**Number.isFinite **检测一个数值是否为有限数

console.log(Number.isFinite(100))       // true
console.log(Number.isFinite(100/0))     // false
console.log(Number.isFinite(Infinity))  // false

Number.isNaN 判断是否为 NaN类型

console.log(Number.isNaN(1))                    // false
console.log(Number.isNaN('2'))                  // false
console.log(Number.isNaN(new Number('3a')))     // false
console.log(Number.isNaN(new Number('a')))      // false
console.log(Number.isNaN(NaN))                  // true

19. ES6 对象方法的拓展

  1. Object.is 判断两个值是否完全相等
console.log(Object.is(NaN, NaN)) // true
console.log(NaN === NaN)         // false
  1. Object.assign 对象的合并
const config1 = {
    host: 'localhost',
    port: 3306,
    username: 'root',
    password: '123456',
}
const config2 = {
    host: '127.0.0.1'
}
console.log(Object.assign(config1, config2))

运行效果
{ host: ‘127.0.0.1’, port: 3306, username: ‘root’, password: ‘123456’ }

  1. Object.setPrototypeOf ,Object.getPrototypeof 给实例对象的构造函数设置原型对象
const user = { name: 'uni'}
const role = { name: '普通用户'}
Object.setPrototypeOf(user, role)
console.log('user:', user)
console.log('getPrototypeOf:', Object.getPrototypeOf(user))

运行结果
user: { name: ‘uni’ }
getPrototypeOf: { name: ‘普通用户’ }

20. ES6 模块化

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

模块化的优势:

  1. 防止命名冲突
  2. 代码服用
  3. 高维护性

ES6 之前的模块化规范:
CommonJS => NodeJS、Browserify
AMD => requireJS
CMD => seaJS
ES6 模块化语法:
模块功能主要由两个命令构成:export 和 import

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

【例】
uni.js

export let name = 'uni'

export function sayHello(){
    console.log(`hi, i am ${name}`)
}

index.html

DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Documenttitle>
  head>
  <body>
    <script type="module">
      import * as uni from './static/uni.js'
      console.log(uni)
    script>    
  body>
html>

运行结果:
JavaScript 笔记1 ES6 新特性 | 解构赋值、模板字符串、Symbol数据类型、Promise、模块化_第4张图片

除了上述的 export 方法以外,还可以统一 export

let name = 'uni'

function sayHello(){
    console.log(`hi, i am ${name}`)
}

export { name, sayHello }

ES6 支持 默认的 export,这样在 import 的时候,需通过 default 来调用里面的属性或方法

export default {
    name: 'uni',
    sayHello(){
      console.log(`hi, i am ${name}`)
    }
}

20.1 import 时使用解构赋值

ES6 支持 解构赋值的方式导入其他的模块

// 导入统一的export
import {name, sayHello} from './static/uni.js'
// 导入默认的export
import {default as uni} from './static/xxx.js'

20.2 默认export的导入

如果要 import 的 js 文件是使用 export default 方式导出的,那么则可以简写import

import xxx from 'xxx.js'

20.3 import 引入的第二种方式

假设 app.js 是 web 程序的入口脚本文件,通常需要引入一些内容
uni.js

export let name = 'uni'

export function sayHello(){
    console.log(`hi, i am ${name}`)
}

app.js

import * as uni from './static/uni.js'
console.log(uni)

index.html

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Documenttitle>
head>
<body>
    <script src="./static/app.js" type="module">script>
body>
html>

20.4 ES6 模块化代码转换

Babel 官网:https://www.babeljs.cn/docs/
Babel 是一个工具链,主要用于将采用 ECMAScript 2015+ 语法编写的代码转换为向后兼容的 JavaScript 语法,以便能够运行在当前和旧版本的浏览器或其他环境中。
这里以了解为主,用到的时候再查阅相关资料

你可能感兴趣的:(学习笔记,javascript,es6,前端)