es6
ES6
210425
1、介绍
-
ECMA:European Computer Manufacturers Association欧洲计算机制造商协会,这个组织的目标是评估、开发和认可电信和计算机标准,94年改名Ecma国际。
-
ECMAScript是由Ecma国际通过ECMA-262标准化的脚本程序设计语言
2、新特性
2.1. let关键字
- 变量不能重复声明
- 块级作用域
- {}
- if
- else
- while
- for
- 不存在变量提升
- 不影响作用域链
<div class="container">
<h2 class="page-header">点击切换颜色</h2>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
<script>
let item = document.getElementsByClassName("item");
//let声明的变量,有块级作用域,互不影响
for(let i = 0; i < item.length;i++){
item[i].onclick = function(){
item[i].style.backgroundColor = 'pink';
}
}
//声明变量
let x;
let b,c,d;
let e = 100;
let f = 423,g = '122ddc',h = [];
//1、变量不能重复声明
let a = '123'; //Identifier 'a' has already been declared
let a = '121';
//2、块级作用域 全局、函数、eval
//if else while for
{
let girl = 'lisa';
}
console.log(girl); //girl is not defined
//3、不存在变量提升
console.log(song); //Cannot access 'song' before initialization
let song = '我们';
//4、不影响作用域链
{
let school = '长沙学院';
function fn(){
console.log(school);
}
fn();
}
</script>
2.2. const关键字
- 一定要赋初始值
- 一般常量使用大写(潜规则)
- 常量的值不能修改
- 块级作用域
- 对于数组和对象元素修改,不算做对常量的修改,不会报错(地址未修改,修改数据不会报错)
const ARR = ['cs','ef','1ds',1];
ARR[0] = 'iwo';
const A = 10;
//const B;报错
//A = 11;报错
2.3. 变量解构赋值
ES6 允许按照一定模式从数组和对象中提取值,对变量进行赋值,这被称为解构赋值
- 数组解构
- 对象解构
//1、数组的解构
const F4 = ['唐僧', '孙悟空', '猪八戒', '沙和尚'];
let [ts, swk, zbj, shs] = F4;
console.log(ts); //唐僧
console.log(swk); //孙悟空
console.log(zbj); //猪八戒
console.log(shs); //沙和尚
//2、对象的解构
const person = {
name: '孙悟空',
age: 18,
say: function () {
console.log("我是唐僧的徒弟");
}
}
let { name, age, say } = person;
console.log(name); //孙悟空
console.log(age); //18
console.log(say); //function这个函数体
say(); //我是唐僧的徒弟
2.4. 模板字符串
ES6 引入新的声明字符串的方式 ``
//ES6 引入新的声明字符串的方式 `` '' ""
//1、声明
let str = `我也是一个字符串哦!`;
console.log(str, typeof str);//string
//2、内容中可以直接出现换行符
let str2 = `<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>`;
//3、变量拼接 ${变量}
let a = '孙悟空';
let b = `${a}七十二变`;//孙悟空七十二变
console.log(b);
2.5. 简化对象写法
ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样书写更加简洁
let name = '孙悟空';
let skill = function(){
console.log('他拥有很多技能!');
}
const person = {
name, //name:name
skill, //skill:skill
flying(){ //省略冒号和function
console.log("他会脚踏祥云");
}
}
console.log(person);
2.6. 函数
2.6.1. 箭头函数
ES6 允许使用箭头 => 定义函数
- this是静态的,this始终指向函数声明时所在作用域下的this的值
- 不能作为构造函数实例化对象
- 不能使用arguments变量
- 箭头函数的简写
- 省略小括号,当形参有且只有一个参数时
- 省略花括号,当代码体只有一条语句时,return必须省略,语句执行结果就是函数的返回值
//声明函数
let fn = (a, b) => {
return a + b;
}
//调用函数
let res = fn(1, 2);
console.log(res);
//1、this是静态的,this始终指向函数声明时所在作用域下的this的值
function getName() {
console.log(this.name);
}
let getName2 = () => {
console.log(this.name);
}
//设置window对象的name属性
window.name = 'phy';
const person = {
name: '孙悟空'
}
//直接调用
getName();//phy
getName2();//phy
//call方法调用
getName.call(person);//孙悟空
getName2.call(person);//phy
//2、不能作为构造函数实例化对象
let Person = (name,age) => {
this.name = name;
this.age = age;
}
let me = new Person('xiao',10);
console.log(me); //Person is not a constructor
//3、不能使用arguments变量
let fn1 = () => {
console.log(arguments);
}
fn1(1,2,3); //arguments is not defined
//4、箭头函数的简写
//1)省略小括号,当形参有且只有一个参数时
let add = n => {
return n + n;
}
console.log(add(9)); //18
//2)省略花括号,当代码体只有一条语句时,return必须省略,语句执行结果就是函数的返回值
let pow = n => n*n;
console.log(pow(9)); //81
2.6.2. 参数默认值
- 形参的初始值,具有默认值的参数,一般位置靠后
- 与解构赋值结合
//es6允许给函数参数赋初始值
//1、形参初始值,具有默认值的参数,一般位置要靠后
function add(a, b, c = 10) {
return a + b + c;
}
console.log(add(1, 2));
//2、与解构赋值结合
function connect({ host, username, password, port }) {
console.log(host);
console.log(username);
console.log(password);
console.log(port);
}
connect({
host: 'baidu.com',
username: 'root',
password: 'root',
port: 3306
})
2.7. rest参数
ES6引入rest参数,用于获取函数的实参,用来代替arguments
ES5获取实参的方式
function data(){
console.log(arguments)
}
data('1','2','3') //输出1,2,3 类型object
rest参数
function data(...args){
console.log(args)
}
data('1','2','3')//1,2,3 类型array,具有数组的方法
//rest参数必须放在参数最后
function fn(a,b,...args){
console.log(a)
console.log(b)
console.log(...args)
}
fn(1,2,3,4,5,6)
2.8. spread扩展运算符
...
扩展运算符能将数组
转换为逗号分隔的参数序列
const arr = [1,2,3]
function fn(){
console.log(arguments)
}
fn(...arr) // fn(1,2,3)
扩展运算符应用
- 数组合并
- 数组克隆 (有引用数据类型是浅拷贝)
- 将伪数组转为真正的数组
//1、数组的合并
const arr1 = [1,2,3]
const arr2 = [4,5,6]
const arr3 = [...arr1,...arr2]
console.log(arr3) //[1,2,3,4,5,6]
//2、数组克隆
const arr = ['A','B','C']
const copyarr = [...arr]
console.log(copyarr)
//3、将伪数组转为真正的数组
const allDivs = doucment.querySelectorAll('div')
const arrDiv = [...allDivs]
console.log(arrDiv) //可以使用数组的方法
2.9. Symbol
ES6引入了一种新的原始数据类型Symbol,表示独一无二的值。是JavaScript语言的第七种数据类型,类似于字符串的数据类型
Symbol特点:
- Symbol的值是唯一的,解决命名冲突的问题
- Symbol值不能与其他数据进行运算
- Symbol定义的对象属性不能使用for..in循环遍历,但可以使用Reflect.ownKeys获取对象的所有键名
2.9.1 Symbol基本使用
//创建Symbol
let s = Symbol()
console.log(s,typeof s)
let s2 = Symbol('phy')
let s3 = Symbol('phy')
console.log(s2 === s3)//false 'phy'只是一个标识名称
//Symbol.for创建
let s4 = Symbol.for('phy')
let s5 = Symbol.for('phy')
console.log(s4 === s5) //true函数对象创建
//不能与其他数据进行运算
let res = s + 100//fault
let res = s > 100//fault
let res = s + s//fault
//JavaScript基本数据类型
//u undefined
//s string symbol
//o object
//n null number
//b boolean
symbol创建对象属性
给对象添加独一无二的属性和方法
//向对象中添加方法 up down
//可以为其对象添加up方法,不影响对象已有的up方法
let game = {
name:"俄罗斯方块",
up:function(){
console.log(1)
}
}
let methods = {
up: Symbol(),
down: Symbol()
}
game[methods.up] = function(){
console.log("我可以改变形状!")
}
game[methods.down] = function(){
console.log("我可以快速下降!")
}
console.log(game)
//方法2
let game2 = {
name:"狼人杀",
[Symbol('say')]:function(){
console.log("我可以发言!")
}
}
console.log(game2)
2.9.2 Symbol内置值
参考文档:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Symbol
- Symbol.hasInstance 当其他对象使用instanceof运算符,判断是否为该实例对象时,会调用这个方法
- Symbol.isConcatSpreadable 该属性是一个布尔值,控制对象用于Array.prototype.concat()时,是否可以展开
//Symbol.hasInstance
//可以获取instanceof前的值
//可以自己控制类型检测
class Person{ //类似构造函数
static [Symbol.hasInstance](param){
console.log(param) //可以获取instanceof前的值
console.log("我被用来检测类型")
return false //可以自己控制类型检测
}
}
let o = {}
console.log(o instanceof Person) //{} 我被用来检测类型 false
//Symbol.isConcatSpreadable
const arr = [1,2,3]
const arr2 = [4,5,6]
arr2[Symbol.isConcatSpreadable] = false
console.log(arr.concat(arr2)) //1,2,3,[4,5,6]
2.10. 迭代器
2.10.1. 介绍
Iterator是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署Iterator接口(对象的一个属性Symbol.iterator),就可以完成遍历操作。
- ES6创造了一种新的遍历命令
for..of
循环,Iterator接口主要供for..of
使用 - 原生具备Iterator接口的数据(可用for of遍历)
- Array
- Arguments
- Set
- Map
- String
- TypeArray
- NodeList
- 工作原理
- 创建一个指针对象,指向当前数据结构的起始位置
- 第一次调用对象的next方法,指针自动指向数据结构的第一个成员
- 接下来不断调用next方法,指针一直往后移动,知道指向最后一个成员
- 每调用next方法返回一个包含value和done属性的对象
- 注:需要自定义遍历数据时,会使用到迭代器
const xiyou = ['唐僧','孙悟空','猪八戒','沙和尚']
//遍历值
for(let v of xiyou){
console.log(v)
}//唐僧 孙悟空 猪八戒 沙和尚
// 遍历下标
for(let v in xiyou){
console.log(v)
}//0 1 2 3
console.log(xiyou) //Symbol.iterator
let iterator = xiyou[Symbol.iterator]();
//调用对象的next方法
console.log(iterator.next()) //{value: "唐僧", done: false}
console.log(iterator.next()) //{value: "孙悟空", done: false}
console.log(iterator.next()) //{value: "猪八戒", done: false}
console.log(iterator.next()) //{value: "沙和尚", done: false}
console.log(iterator.next()) //{value: undefined, done: true} done判断是否结束
2.10.2. 应用
const banji = {
name: "终极一班",
stus: [
'tom',
'bob',
'lisa',
'susan'
],
[Symbol.iterator]() {
let index = 0
let _this = this
return {
next: function () {
if (index < _this.stus.length) {
const res = { value: _this.stus[index], done: false }
index++
return res
} else {
return { value: undefined, done: true }
}
}
}
}
}
// 遍历这个对象
for (let v of banji.stus) {
console.log(v)
}
2.11. 生成器
是一个特殊的函数,是一种异步编程解决方案,语法行为与传统函数完全不同
2.11.1. 使用
function* gen1() {
console.log("hello generator")
}
let iterator1 = gen1()
console.log(iterator1)
// 调用
iterator1.next() //hello generator
function* gen() {
//函数代码的分隔符 next()执行
console.log(111)
yield '一只没有耳朵'
console.log(222)
yield '一只没有尾巴'
console.log(333)
yield '真奇怪'
console.log(444)
}
let iterator = gen()
iterator.next()//111
iterator.next()//222
iterator.next()//333
iterator.next()//444
//遍历
for(let v of gen()){
console.log(v) //yield的值
}
2.11.2. 生成器函数参数
- 函数可以传形参
- next方法种可以传入实参
//可以对函数传参
function * gen(arg){
console.log(arg) //AAA
let one = yield 111
console.log(one) //BBB
let two = yield 222
console.log(two) //CCC
let three = yield 333
console.log(three) //DDD
}
let iterator = gen('AAA')
// next方法可以传入实参
console.log(iterator.next()) //{value: 111, done: false}
// 参数将会作为上一个yield语句的返回结果
console.log(iterator.next('BBB')) //{value: 222, done: false}
console.log(iterator.next('CCC')) //{value: 333, done: false}
console.log(iterator.next('DDD')) //{value: undefined, done: true}
2.11.3. 生成器函数实例
// 生成器解决回调地狱问题
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 getNames() {
setTimeout(()=>{
let data = '用户数据'
// 调用next方法,传入数据
iterator.next(data)//第二次调用next,data将会作为第一个yield的实参
},1000)
}
function getOrders() {
setTimeout(()=>{
let data = '订单数据'
iterator.next(data)
},1000)
}
function getGoods() {
setTimeout(()=>{
let data = '商品数据'
iterator.next(data)
},1000)
}
function * gen(){
let name = yield getNames()
console.log(name) //用户数据
let order = yield getOrders()
console.log(order) //订单数据
let good = yield getGoods()
console.log(good) //商品数据
}
//调用生成器函数
let iterator = gen()
iterator.next()
2.12. Promise
是ES6引入的异步编程的新解决方案。语法上Promise是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果
- Promise构造函数:Promise(excutor){}
- Promise.prototype.then()方法
- Promise.prototype.catch()方法
2.12.1. 使用
//实例化Promise对象,可以通过resolve与reject改变p的状态
const p = new Promise(function (resolve, reject) {
// let data = '数据库中的用户数据'
// resolve(data)
let err = '读取数据失败'
reject(err)
})
// 调用promise对象的then方法
p.then(function (value) {
console.log(value)
}, function (err) {
console.log(err)
})
2.12.2. promise读取文件
const fs = require('fs')
// fs.readFile('./1.txt',(err,data)=>{
// if(err) throw err
// console.log(data.toString())
// })
// 使用promise封装
const p = new Promise((resolve, reject) => {
fs.readFile('./1.txt', (err, data) => {
if (err) reject(err)
resolve(data)
})
})
p.then(function (value) {
console.log(value.toString())
}, function (reason) {
console.log("读取失败!!")
})
2.12.3. promise封装AJAX
const p = new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('get', 'https://api.apiopen.top/getJoke')
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.error(reason)
})
2.12.4. promise-then方法
const p = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('用户数据')
},1000)
})
//调用then方法 then方法得返回结果是promise对象,对象状态由回调函数的执行结果决定
//1、如果回调函数中返回的结果是非promise类型的属性,状态为成功,返回值为对象的成功的值
const res = p.then(value => {
console.log(value)
//1、非promise类型的属性:undefined字符串数字
//return 123
//2、是promise对象
return new Promise((resolve,reject)=>{
//会影响then方法的状态
//resolve('ok')
reject('error')
})
//3、抛出错误
//throw new Error('出错啦!')
throw '出错啦!'
},reason => {
console.warn(reason)
})
console.log(res)
2.12.5. promise读取多个文件内容
const fs = require('fs')
const p = new Promise((resolve, reject) => {
fs.readFile('./1.txt', (err, data) => {
resolve(data)
})
})
p.then(value => {
return new Promise((resolve, reject) => {
fs.readFile('./2.txt', (err, data) => {
resolve([value, data])
})
})
}).then(value => {
return new Promise((resolve, reject) => {
fs.readFile('./3.txt', (err, data) => {
value.push(data)
resolve(value)
})
})
}).then(value => {
console.log(value.join('\r\n'))
})
2.12.6. promise-catch方法
处理拒绝的情况
const p = new Promise((resolve,reject)=>{
setTimeout(()=>{
reject("出错啦!");
},1000)
})
p.catch((reson)=>{
console.warn(reason)
})
2.13. Set
新的数据结构Set(集合),类似于数组,但成员的值都是唯一的,集合实现了iterator接口,可以使用扩展运算符
和for..of..
进行遍历。
集合的属性和方法:
- size 返回集合的元素个数
- add 增加一个新的元素,返回当前集合
- delete 删除元素,返回boolean值
- has 检测集合中是否包含某个元素,返回boolean值
- clear 清空
2.13.1. 使用
//声明一个集合
let s = new Set()
let s2 = new Set(['A','B','C','D','A'])
//元素个数
console.log(s2.size) //4
//添加元素
s2.add('N') //'A','B','C','D','N'
//删除元素
s2.delete('D') //'A','B','C','N'
//检测
s2.has('M') //false
//清空
s2.clear()
console.log(s2)
for(let v of s2){
console.log(v)
}
2.13.2. 集合实践
let arr = [1,2,1,3,4,5,4,6,4,0,7,8,9]
//1、数组去重
let res = [...new Set(arr)]
console.log(res)
//2、交集
let arr2 = [4,4,3,1,2]
let res2 = [...new Set(arr)].filter(item => {
let s2 = new Set(arr2)
if(s2.has(item)){
return true
}else{
return false
}
})
let res3 = [...new Set(arr)].filter(item => new Set(arr2).has(item))
console.log(res3)
//并集
let union = [...new Set([...arr,...arr2])]
//差集
let diff = [...new Set(arr)].filter(item =>!(new Set(arr2).has(item)))
2.14. Map
类似于对象,键值对集合。键的范围不限于字符串,各种类型的值(包括对象)都可以当作键,Map也实现了iterator接口,可以使用扩展运算符
和for..of..
进行遍历。
- Map对象保存键值对,按键的原始插入顺序,任何值都可以作为一个键或一个值
- 计算一个
Map
的条目数量,使用Map.prototype.size
,不用length
Map.prototype.clear()
移出Map对象所有的键值对Map.prototype.get(key)
返回键对应的值Map.prototype.has(key)
判断是否包含键对应的值Map.prototype.set(key,value)
设置Map对象中键的值Map.prototype.keys()
获取Map对象中所有的键Map.prototype.values()
获取Map对象中所有的值Map.prototype.forEach(callback)
为Map对象中的每一个键值对调用一次callback函数Map.prototype.entries()
包含Map对象中每个元素的key和value数组
//声明
let m = new Map()
//添加元素
m.set('name','phy')
m.set('change',function(){
console.log("你会变得更好!")
})
let key = {
province:'CHANGSHA'
}
m.set(key,['橘子洲','五一广场','坡子街','国金中心'])
//输出长度
console.log(m.size)
//删除
m.delete('name')
//获取
console.log(m.get('change'))
//清空
m.clear()
//遍历,输出数组键值
for(let v of m){
console.log(v)
}
2.15. class类
通过class关键字,可以定义类。基本上ES6的class可以看作只是一个语法糖,绝大部分功能,ES5可以实现,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
- class声明类
- constructor定义构造函数初始化
- extends继承父类
- super调用父级构造方法
- static定义静态方法和属性
- 父类方法可以重写
2.15.1. 基本使用
// ES5
function Phone(brand, price) {
this.brand = brand
this.price = price
}
//add method
Phone.prototype.call = function () {
console.log("i can make a phone call")
}
//实例化对象
let xm = new Phone('小米',3999)
xm.call()
console.log(xm)
//ES6
class Phone{
// 构造方法 名字不能修改
constructor(brand,price){
this.brand = brand
this.price = price
}
// 方法必须使用‘函数名()’的形式,不能使用ES5的对象完整形式
call(){
console.log('i can make a phone call')
}
}
let xm = new Phone('xiaomi',3299)
xm.call()
console.log(xm)
2.15.2. 类的静态成员
//属于类不属于实例对象
//es5
class Phone{}
Phone.name = 'phone'
Phone.change = function(){
console.log('i can change the world')
}
Phone.prototype.size = '5.5inch'
let xm = new Phone()
console.log(xm.name) //undefined
console.log(xm.size) //5.5inch
//es6
class Phone{
static name = 'phone'
static change(){
console.log("i can change the world")
}
}
let xm = new Phone()
console.log(xm.name) //undefined
console.log(Phone.name) //phone
2.15.3. 对象继承
//es5
// 父类
function Phone(brand, price) {
this.brand = brand
this.price = price
}
Phone.prototype.call = function () {
console.log('i can make a phone call')
}
// 智能手机
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('take phone')
}
SmartPhone.prototype.play = function () {
console.log('play game')
}
const xm = new SmartPhone('xiaomi', 3299, 'black', '5.6inch')
console.log(xm)
//es6
class Phone{
constructor(brand,price){
this.brand = brand
this.price = price
}
call(){
console.log("i can make a phone call")
}
}
class SmartPhone extends Phone{
constructor(brand,price,color,size){
super(brand,price)
this.color = color
this.size = size
}
photo(){
console.log("take photo")
}
play(){
console.log('play game')
}
//重写 不能调用父类同名的方法
call(){
console.log('i can video call')
}
}
const xm = new SmartPhone('xiaomi',3499,'red','6.5inch')
console.log(xm)
xm.photo()
xm.call()
2.15.4. set-get
class Phone{
get price(){
console.log("价格属性被读取了")
return 'a'
}
set price(newVal){
console.log("价格属性被修改了")
}
}
// 实例化对象
let s = new Phone()
s.price
s.price = 'free'
2.16. 数值扩展
// 0.Number.EPSILON是Javascript表示的最小精度
// EPSILON属性的值接近于2.22-16
console.log(0.1 + 0.2 === 0.3) //false
function equal(a, b) {
if (Math.abs(a - b) < Number.EPSILON)
return true
else
return false
}
console.log(0.1 + 0.2 === 0.3) //false
console.log(equal(0.1 + 0.2, 0.3)) //true
//1.二进制和八进制
let b = 0b1010 //二进制
let o = 0o777 //八进制
let d = 100 //十进制
let x = 0xff //十六进制
console.log(b,o,d,x)
//2、Number.isFinite 检测一个数值是否为有限
console.log(Number.isFinite(100)) //true
console.log(Number.isFinite(100/0)) //false
console.log(Number.isFinite(Infinity)) //false
//3、Number.isNaN 检测一个数值是否为NaN
console.log(Number.isNaN(123))
// 4、Number.parseInt Number.parseFloat字符串转整数
console.log(Number.parseInt('19328djd')) //19328
console.log(Number.parseFloat('3.1415926jsiodj')) //3.1415926
// 5、Number.isInteger判断一个数是否为整数
console.log(Number.isInteger(5))//true
console.log(Number.isInteger(5.5)) //false
//6、Math.trunc将数字的小数部分抹掉
console.log(Math.trunc(3.5)) //3
//7、Math.sign判断一个数是正数、负数、0
console.log(Math.sign(100)) //1
console.log(Math.sign(0)) //0
console.log(Math.sign(-100)) //-1
2.17. 对象扩展
//1、Object.is 判断两个数是否完全相等
console.log(Object.is(12,12))//true
console.log(Object.is(NaN,NaN))//true
console.log(NaN===NaN)//false
//2、Object.assign 对象的合并
const obj1 = {
name: 'phy',
age: 18
}
const obj2 = {
name: 'Tom'
}
//两个对象中相同元素会被覆盖
console.log(Object.assign(obj1,obj2)) //{name:"Tom",age:18}
//3、Object.setPrototypeOf设置原型对象 Object.getPrototypeOf
const area = {
name: 'China'
}
const cities = {
province:['chnagsha','beijing','shanghai']
}
Object.setPrototypeOf(area,cities)
console.log(Object.getPrototypeOf(area))
console.log(school)
2.18. 模块化
模块化是指将一个大的程序文件,拆分为许多小的文件,将小文件组合起来。
模块化的优势
- 防止命名冲突
- 代码复用
- 高维护性
模块化规范产品
- CommonJS => NodeJS,Browserify
- AMD => requireJS
- CMD => seaJS
ES6模块化语法
模块功能主要由两个命令构成:export和import
- export命令用于规定模块的对外接口
- import命令用于输入其他模块提供的功能
使用
方法一:
<script type="module">
//1.通用导入方式
import * as m from './m.js'
console.log(m)
//默认暴露调用的方式
m.default.change()
//2.解构赋值形式
import {name as n,moody} from './m.js'
//导入默认暴露的模块需要别名
import {default as d} from './m.js'
console.log(name)
console.log(moody)
//3简便形式 针对默认暴露
import m from './m.js'
console.log(m)
</script>
m.js
//分别暴露
export let name = 'phy'
export function moody(){
console.log("unhappy,today is terrible")
}
//统一暴露
export {name,moody}
//默认暴露
export default{
change: function(){
console.log('we will change you')
}
}
方法二:
app.js
import * as m from './m.js'
html
<script src='./m.js' type="module"></script>
Babel
将es6语法转换成es5浏览器可以识别的JavaScript
-
安装工具 babel-cli(命令行工具) babel-preset-env(转换工具) browserify(打包工具)
npm i babel-cli babel-preset-env browserify -D
-
npm babel 源文件目录src/js -d 保存至文件目录dist/js
-
打包 npx browserify dist/js/app.js -o dist/bundle.js
-
问题
babel & browserify 报错 'import' and 'export' may appear only with 'sourceType: module'
新建
.babelrc
文件{ "presets": ["es2015","stage-0"] }
安装
cnpm i -D babel-preset-stage-0 #使用 #转换 npx babel js -d dist/js --presets-babel-preset-env #打包 npx browserify dist/js/app.js -o dist/bundle.js
ES6中模块引入NPM包
- 安装
npm i jquery -S
- 转换
npx babel js -d dist/js --presets-babel-preset-env
- 打包
npx browserify dist/js/app.js -o dist/bundle.js
- 浏览器打开html文件即可
app.js
import * as m from './m.js'
import $ from 'jquery'
$('body').css('background','pink')
m.moody()
console.log(m.name)
m.js
export let name = 'phy'
export function moody(){
console.log("unhappy,today is terrible")
}
index.html
<script src="dist/bundle.js"></script>