ECMAScript6
ES5语言先天性不足。变量提升、内置对象的方法不灵活、模块化实现不完善
文章目录
1.ES6简介
1.1概念
ES6泛指5.1版本后的JavaScript的下一代标准,2015年开始
1.2浏览器支持
kangax-compat-table/es6 at gh-pages · GerHobbelt/kangax-compat-table (github.com)
超过90%ES6语法特性已实现
前端工具babel,JavaScript编译器,可以将es6代码转换成es5代码,以获得浏览器支持
2.ES6新特性
2.1 let和const命令
-
var 会变量提升(含var语句会提至最开始执行)
-
let
- 没有变量提升
- 是一个块级作用域(只作用在一个{}内)更严谨
- 不能重复声明
-
const
- 没有变量提升
- 块级作用域
- 不能重复声明
- 声明的是个常量,后续不能再改变,但可以修改声明对象的属性
- 方便作为第三方框架引入, 变量不被随意修改
-
案例1 for循环用来计数的循环遍历泄露为全局变量:
var arr = []; for(var i =0;i<10;i++){ arr[i]=function(){ return i; } } console.log(arr[5]());
打印结果:10
原因:循环执行结束后i变成了10,由于变量提升,再次执行函数,for循环前i=10,就都返回10
解决,使用let 这样作用域限定在for循环内
const arr =[]; for(let i =0;i<10;i++){ arr[i]=function(){ return i; } } console.log(arr[5]());
打印结果:5
-
案例2 使用let/const避免污染全局变量:
let RegExp =10; console.log(RegExp); console.log(window.RegExp);
打印结果:10 RegExp()
-
建议:默认情况用const,已知变量值需要修改使用let
2.2 es6的模板字符串
-
模板字符串:使用反引号``,插入变量时使用${变量名}
-
使用场景:后端返回长文本等数据,使用模板字符串拼接追加更方便
-
案例:
<div class="box"></div> <script> const oBox = document.querySelector('.box'); let id =1, name=ddd; let htmlStr=`<ul> <li> <p id=${id}>${name}</p> </li> </ul>`; //oBox.innerHTML="<ul><li><p id="+id+">"+name+"</p></li></ul>" //利用模板字符串简化追加结构 oBox.innerHTML=htmlStr; </script>
2.3 增强的函数
2.3.1 默认值
-
带参数默认值的函数
//es5 function add(a,b){ a = a||10; b = b||20; return a+b; } console.log(add()); //es6 function add1(a=10,b=20){ return a + b; } console.log(add1()); function add2(a,b=20){ return a + b; } console.log(add2(30));
打印结果
30 30 50
-
默认的表达式也可以是一个函数
function add(a,b=getVal(5)){ return a + b; } function getVal(val){ return val + 5; } console.log(add(10));
打印结果
20
2.3.2 剩余参数
-
由三个点…和一个紧跟着的具名参数指定 …keys
-
…keys 解决了arguments的问题
-
案例
function pick(obj, ...keys){ //生成一个空数组 let result = Object.create(null); for (let i = 0;i<keys.length;i++){ result[keys[i]]= obj[keys[i]]; } return result; } let book ={ tittle:'es6', author:'ddd', year:2023 } let bookData = pick(book,'year','author'); //{'year','author'}作为剩余参数被...keys包裹,替代Arguments伪数组
打印结果
{year:2023,author:"ddd"}
2.3.3 扩展运算符
-
用…实现
-
剩余运算符:把多个独立的合并到一个数组中,一般放在函数形参上
-
扩展运算符:将一个数组分割,并将各个项作为分离的参数传给函数
-
案例
const arr =[10,20,30,50,90,100,40]; //es5 处理数组中的最大值,使用apply //console.log(Math.max.apply(null,arr)); //es6 扩展运算符更方便 将数组分割每个参数传递给Math.max console.log(Math.max(...arr));
打印结果
100
2.3.4 箭头函数
-
使用
=>
来定义function(){}
等于()=>{}
-
案例
//es5 let add = function(a,b){ return a+b; } //es6 //多个参数 let add =(a,b)=>{ return a+b; } //一个参数,没有参数()需要保留 let add =val=>{ return val+5; } //可以省略{return},=>就代表返回,返回值可以不加括号,若返回一个数组或对象,需要最外层用()包裹 let add =(val1,val2)=> val1+val2;
//es5闭包函数 let fn =(function(){ return function(){ console.log('hello es6'); } })(); //es6 let fn =(()=>{ return ()=>{ console.log('hello es6'); } })();
-
this指向
-
es5中this指向:取决于调用该函数的上下文对象
-
案例
let PageHandle = { id:123, init: function(){ document.addEventListener('click',function(event){ //报错 this.doSomeThing is not a function,因为this指向为document 不再是PageHandle //可以用bind改变内部this指向 this.doSomeThings(event.type); }.bind(this),false) }, doSomeThings: function(type){ console.log(`事件类型:${type},当前id:${this.id}`); } }
es6解决:利用箭头函数,箭头函数没有this指向,内部this查找上层函数作用域(链)来确定(一旦使用箭头函数,当前不存在作用域)
let PageHandle = { id: 123, init: function(){ //箭头函数没有作用域,内部this查找作用域链-上一层 谁定义了init函数就指向谁 document.addEventListener('click',(event)=>{ console.log(this); this.doSomeThings(event.type); },false) }, doSomeThings: function (type){ console.log(`事件类型:${type},当前id:${this.id}`); } }
-
注意事项:
-
使用箭头函数,函数内部没有arguments
-
箭头函数不能使用new关键字实例化对象
let Person = ()=>{ }; let p = new Person(); //报错 function函数也是一个对象,箭头函数不是对象,其实就是一个语法糖,没有constructor
-
-
2.4 解构赋值
-
对赋值运算符的一种扩展
-
针对数组和对象来进行操作
-
优点:代码书写简洁易懂
-
案例
对对象进行解构
let node ={ type: 'id', name: 'ddd' } /*es5 let type = node.type; let name = node.name;*/ //es6解构赋值 //完全解构 let {type,name} = node; console.log(type,name); let obj = { a:{ name:"张三" }, b:[], c:'hello,world' } //不完全解构 可忽略某些属性 let {a} = obj; console.log(a); //剩余运算符 let {a,...res}= obj; //默认值 let {a,b=30}={a:20};
对数组进行解构
let arr =[1,2,3]; let [a,b]=arr;//不完全解构 let [a,b,c]=arr;//完全解构 //对数组嵌套解构 let [a,[b],c] = [1,[2],3];
2.5 扩展的对象的功能
-
es6允许直接写入变量和函数作为变量的属性和方法
//eg1 const name ='ddd',age=20; const person ={ name, age, sayName(){ console.log(this.name); } } person.sayName(); //eg2 function fn(x,y){ return {x,y}; //es5 //return {x:x,y:y}; } console.log(fn(10,20)); //eg3属性的赋值器setter和取值器getter let cart ={ wheel:4, set(newVal){ if(newVal<this.wheel){ throw new Error('轮子数过少,请重设') } this.wheel = newVal; }, get(){ return this.wheel; } } cart.set(6); console.log(cart.get());
-
注意:简写的对象方法不能当作构造函数使用
-
es6允许用表达式作为属性名,将表达式放在方括号内
const name='a'; const obj = { isShow:true, [name+'bc']:123, ['f'+name](){ console.log(this); } }
-
对象的扩展方法
-
**
is()
**比较两个值是否严格相等,等价于===
,区别在于更严格,eg
console.log(Object.is(NaN,NaN))//true
console.log(NaN === NaN);//false
-
**
assign()
**对象的合并Object.assign(target,obj1,obj2.....)
将obj1,obj2…的所有属性都合并到target对象并进行返回let newObj = Object.assign({},{a:1},{b:2}); console.log(newObj);//output: {a:1,b:2}
-
2.6 Symbol
-
一个新的原始数据类型,它表示是独一无二的值,内存地址不相同
-
主要用途:用来定义对象的私有变量
-
案例
const name = Symbol('name'); const name2 = Symbol('name'); console.log(name === name2);//false let s1 = Symbol('s1'); let obj ={ [s1]:'ddd' }; //obj[s1]='ddd'; console.log(obj[s1]);//ddd
注意:使用Symbol定义的对象中的变量,取值必须用**[变量名]**
-
缺点:
- 不易对对象的属性进行操作,比如不能用for循环取出对象中Symbol声明的属性
- 解决:
let s =Object.getOwnPropertySymbols(obj);
let m = Reflect.ownKeys(obj);
2.7 Map和Set
2.7.1 Set
-
又名集合,无重复值的有序列表
-
set的方法
let set = new Set(); //添加元素 set.add(2); set.add('4'); set.add([1,2,3]); //删除元素 set.delete(2); //校验某个值是否在set中 console.log(set.has('4')); //集合的长度 console.log(set.size); //利用扩展运算符将set转换为数组 let set2 = new Set([1,2,3,3,4]); let arr = [...set2]; console.log(arr);
-
注意:set中对象的引用无法被释放
let set3 = new Set(),obj = {}; set3.add(obj); //释放当前的资源 不成功 obj = null; console.log(set3); //解决方法 WeakSet() let set4 = new WeakSet(),obj = {}; set4.add(obj); obj = null; console.log(set4);
2.7.2 Map
-
Map类型是键值对的有序列表,键和值可以是任意类型
-
Map的方法
let map = new Map(); //添加键值对 map.set('name','张三'); map.set('age',20); //根据键获取值 console.log(map.get('name')); //检验是否存在 map.has('name');//true //删除 map.delete('name'); //清空 map.clear(); //一次性定义含多个键值对的map let m = new Map([ ['a',1], ['c',2] ]); //和set一样不能释放引用对象,用WeakMap解决
2.8 数组的扩展方法
-
from()
将伪数组转换为真数组function add(){ //es5转换 let arr1 =[].slice.call(arguments); //es6 let arr2 =Array.from(arguments); } add(1,2,3);
<ul> <li>1</li> <li>2</li> <li>3</li> </ul> <script> let lis = document.querySelectorAll('li'); console.log(Array.from(lis));//{li,li,li} //通过扩展运算符 也可将伪数组转换为真正数组 console.log([...lis]); </script>
注意:
from()
还可以接收第二个参数(一个回调函数),用来对每个元素进行处理let liContents = Array.from(lis,ele => ele.textContent);//ele就是element的简写 console.log(liContents);//{"1","2","3"}
-
of()
将一组任意数据类型的值转换为数组console.log(Array.of(3,11,20,'30'));//{3,11,20,"30"}
-
copywithin()
将数组中指定位置元素复制到其他位置,返回当前数组console.log([1,2,3,8,9,10].copyWithin(0,3));//3号位及以后的元素复制到0号位开始 并覆盖掉原数值 //结果{8,9,10,8,9,10}
-
find()
查找元素findIndex()
查找元素索引值//找出第一个符合条件的数组成员 let num = [1,2,-10,-20,9,2].find(n => n<0); console.log(num);//-10
//找出第一个符合条件的数组成员的索引 let index = [1,2,-10,-20,9,2].findIndex(n => n<0); console.log(index);//2
-
entries()
keys()
values()
返回一个遍历器 可以使用for…of循环进行//遍历键名 for (let index of ['a','b'].keys()){ console.log(index);//0 1 } //遍历值 for (let ele of ['a','b'].values()){ console.log(ele);//a b } //遍历键值对 for (let [index,ele] of ['a','b'].entries()){ console.log(index,ele);//0"a" 1"b" }
-
includes()
判断数组是否包换给定的值,返回一个布尔型console.log([1,2,3].includes(2));//true console.log([1,2,3].includes('4'));//false //之前 indexOf()需要判断返回值-1 1 的含义 麻烦 console.log([1,2,3].indexOf('2'));//-1 console.log([1,2,3].indexOf(2));//1
2.9 迭代器和生成器
2.9.1 迭代器(遍历器)Tterator
-
es6引入的新的遍历机制,是一个接口,作用是使各种数据结构能被快捷访问,通过Symbol.iterator生成
-
案例
//使用迭代 const items = ['one','two','three']; //1.创建新的迭代器 const ite = items[Symbol.iterator](); console.log(ite.next());//{value:"one",done:false}done表示是否遍历完成,false即还可遍历,最后一次value为undefined console.log(ite.next());//{value:"two",done:false}
-
迭代器是一个能快捷访问数据的接口,通过Symbol.iterator创建迭代器,通过迭代器的
next()
获取迭代之后的结果 -
迭代器可以看作用于遍历数据结构的指针(数据库的游标)
2.9.2 生成器Generator
-
与迭代器紧密相关,
generator
是一种新的函数类型,它可以在执行过程中暂停并再次恢复 -
通过使用关键字
function*
来定义一个generator
函数,generator
函数内部使用yield
关键字可以使函数在每次调用时产生一个值,并暂停执行。这使得generator
函数可以用于实现迭代器或者异步操作。 -
与普通函数区别
- function后 函数名前 有个*****
- 只能在函数**内部使用
yield
**表达式,让函数挂起
-
案例(普通用法)
function* func(){ console.log('start'); yield 2; yield 3; } let fn = func();//没有输出 console.log(fn.next());
//打印结果 start {value: 2, done: false}
-
解释:调用
generator
函数不会进入函数内部,而是返回一个遍历器对象,可以调用next()
,每次调用 指针指向下一个yield
处 获取此前结果,随后挂起 -
总结:
generator
函数分段执行,可以理解为yield
语句暂停执行,next()
恢复执行 -
next()
传值function* add(){ console.log('start'); let x = yield '2'; console.log('one:'+x); let y = yield '3'; console.log('two:'+y); return x+y; } const fn = add(); console.log(fn.next()); console.log(fn.next());//在此处传值才会给yield'2'(x) //修改上一行代码 console.log(fn.next(20)); //第三次调用 console.log(fn.next(30));//y被赋值为30
//打印结果 start {value:"2",done: false} one:undefined {value:"3",done: false}//因为x没有被赋值 //修改后的第二次next执行结果 one:20 {value:"3",done: false} //第三次next执行结果 two:30 {value:50,done:true}//value值就是return值,遇到return, done=>true
x不是yield语句返回值,是next()调用,恢复当前yield执行传入的实参
-
使用场景:为不具备Iterator接口的对象提供了遍历操作
//生成器函数 function* objectEntries(obj){ //获取对象的所有key保存到数组[name,age] const propKeys = Object.keys(obj); for(const propkey of propKeys){ yield [propkey,obj[propkey]] } } const obj = { name:'ddd', age:18 } //用生成器给对象创建了一个遍历器 obj[Symbol.iterator] = objectEntries; console.log(obj); //可以使用for of 遍历遍历器了,每次[key,value]相当于next for(let [key,value] of objectEntries(obj)){ console.log(`${key}:${value}`); }
//打印结果 {name:"ddd",age:18,Symbol(Symbol.iterator):f} name:ddd age:18
-
应用:解决异步编程,部署ajax操作,让异步代码同步化
//回调地狱 $.ajax({ url:'', method:'get', success(res){ console.log(res); //继续发送请求 $.ajax({ url:'', method:'get', success(res1){ //发送ajax $.ajax({ url:'', method:'get', success(res2){ //发送ajax $ } }) } }) } }) //利用生成器修改成同步 function* main(){ let res = yield request(''); console.log(res); //发送请求完成后执行后面的操作 console.log('数据请求完成,可以继续操作'); } const ite = main(); ite.next(); function request(url){ $.ajax({ url, method:'get', success(res){ ite.next(res);//传值给了res } }) }
//加载loading...页面 //数据加载完成...(异步操作) //loading关闭掉 function loadUI(){ console.log('加载loading...页面'); } function showData(){ setTimeout(()=>{ console.log('数据加载完毕'); },1000); } function hideUI(){ console.log('隐藏loading...页面'); } loadUI(); showData(); hideUI(); //无法控制输出 hideUI比showData晚执行
//要把以上的异步改成我们需要的方式 而不是直接依次发生 //利用生成器 function* load(){ loadUI(); yield showData(); hideUI(); } //创建一个生成器 let itLoad = load(); //调用next(),等于执行 loadUI showData 然后挂起 itLoad.next(); function loadUI(){ console.log('加载loading...页面'); } function showData(){ //模拟异步操作 setTimeout(()=>{ console.log('数据加载完毕'); //数据加载完毕 再次调用next(),继续执行hideUI itLoad.next(); },1000); } function hideUI(){ console.log('隐藏loading...页面'); }
2.10 Promise对象
2.10.1 Promise的基本使用
-
promise 承诺
-
相当于一个容器,保存着未来才会结束的事件(异步操作)的一个结果
-
各种异步操作都可以用同样的方法进行处理 axios内部实现通过promise
-
特点:
- 对象的状态不受外界影响 处理异步操作有三个状态 Pending(进行中) Resolved(成功) Rejected(失败)
- 一旦Promise对象的状态从pending转变为fulfilled或rejected,就会触发相应的处理程序
- 一旦状态改变就不会回退,任何时候都可以通过对象获取状态结果
- 创建一个Promise对象时,需要传入一个执行器函数,该函数接受两个参数:resolve和reject。在执行器函数中执行异步操作,并根据操作结果调用resolve或reject方法来改变Promise的状态。
-
作用:更清晰地表达和处理异步操作,避免了回调地狱(callback hell),使得异步代码更易读、易维护
-
使用案例:
let pro = new Promise(function(resolved,rejected){ //执行异步操作 let res = { code: 200, data:{ name:'ddd' } err:'failed' } setTimeout(()=>{ if(res.code === 200){ resolved(res.data); }else{ rejected(res.error); } },1000); }) console.log(pro); pro.then((val)=>{ console.log(val); },(err)=>{ console.log(err); });
//封装 实现从外界传入timeOut时间参数 function timeOut(ms){ return new Promise((resolved,rejected)=>{ setTimeOut(()=>{ resolved('hello promise success!!') },ms); }) } timeOut(2000).then((val)=>{ console.log(val); })
2.10.2 使用Promise封装ajax
-
封装异步操作 外面声明一个函数在函数中返回一个promise(因为promise函数不能传参),通过promise对异步操作进行链式调用(.then().then().catch()…)
const getJSON = function(url){ return new Promise((resolve,reject)=>{ const xhr = new XMLHttpRequest(); xhr.open('GET',url); xhr.onreadystatechange = handler; xhr.responseType = 'json'; xhr.setRequestHeader('Accept','application/json'); xhr.send(); function handler(){ //this 指向 xhr if(this.readyState === 4){ if(this.status === 200){ resolve(this.response); }else{ reject(new Error(this.statusText)); } } } }) } getJSON('https://leetcode.cn/studyplan/top-100-liked/') .then((data)=>{ console.log(data);//返回response },(error)=>{ console.log(error);//返回错误信息 })
-
then()
方法,第一个参数是resolve回调函数,第二个参数是可选的,是reject状态回调函数 -
then()
返回一个新的promise实例,可以采用链式编程 -
.catch(err=>{})
等价于.then(null,err=>{})
getJSON('https://leetcode.cn/studyplan/top-100-liked/') .then(data=>{ console.log(data);//.then捕获成功 }).catch(err=>{ console.log(err);//.catch捕获失败 })
2.10.3 promise对象的其他方法
-
resolve()
将一个现有的任何对象(函数参数)转换为promise对象,随后拥有状态,可以通过.then .catch去获取let p =Promise.resolve('foo'); //let p = new Promise(resolve=>resolve('foo')); //let p = new Promise(resolve =>{ // return resolve('foo'); //}) //以上三者等价 p.then((data)=>{ console.log(data); })
-
reject()
也返回Promise
实例,和resolve()
一样 -
all()
提供了并行地执行异步操作的方式。一些游戏类的素材比较多,等待图片,flash,静态资源文件都加载完毕,才进行页面的初始化let promise1 = new Promise((resolve,reject)=>{}); let promise2 = new Promise((resolve,reject)=>{}); let promise3 = new Promise((resolve,reject)=>{}); let p4 = Promise.all([promise1,promise2,promise3])//p4也是一个promise实例 p4.then(()=>{ //三个都成功 才成功 并行执行异步操作 }).catch(err=>{ //如果有一个失败 则失败 })
-
race()
它接受一个可迭代对象作为参数(通常是一个包含多个Promise
实例的数组),并返回一个新的Promise
对象。这个新的Promise
对象会在可迭代对象中的第一个Promise
对象状态发生改变时采用该状态值(无论是成功 (fulfilled
) 还是失败 (rejected
)-采用第一个失败Promise
的拒绝原因)。应用在给某个异步操作设置请求超时时间,并在超时后执行相应操作。
eg1:
如果你有一个包含两个
Promise
实例的数组,其中一个会在 500 毫秒后成功,另一个会在 1000 毫秒后失败,那么使用Promise.race
来处理这个数组将会返回一个新的Promise
对象。这个新的Promise
对象会在第一个Promise
的状态发生改变后立即采用该状态,并将其传递给相应的处理程序。const promise1 = new Promise((resolve, reject) => { setTimeout(resolve, 500, 'one'); }); const promise2 = new Promise((resolve, reject) => { setTimeout(reject, 1000, 'two'); }); Promise.race([promise1, promise2]) .then(value => { console.log(value); // 输出 "one" }) .catch(reason => { // 这里不会执行 });
promise1
在 500 毫秒后已经成功,因此Promise.race
返回的新Promise
对象立即就会采用成功状态,并将'one'
作为成功的值传递给.then
处理程序。若
promise1
在 500 毫秒后已经失败reject
,Promise.race
返回的新Promise
对象立即就会变为失败状态,并且采用'one'
作为拒绝的原因,若promise2
成功,其状态不会对新Promise
对象产生任何影响。//eg2 请求图片资源 function requestImg(imgSrc){ return new Promise((resolve,reject)=>{ const img = new Image(); img.onload = function(){ resolve(img); } img.src = imgSrc; }); } function timeout(){ return new Promise((resolve,reject)=>{ setTimeout(()=>{ reject('图片请求超时'); },3000); }) } Promise.race([requestImg('images/2.jpg'),timeout()]).then(data=>{ console.log(data);//3s内成功获得图片则执行该行代码 document.body.appendChild(data); }).catch(err=>{ console.log(err);//3s内不能获取则执行此 })
-
done()
无论新promise对象状态成功or失败,done()
都会执行 -
finally()
无论新promise对象状态成功or失败,finally()
都会执行
2.11 async的用法
-
async
是用于定义异步函数的关键字 -
解决异步操作的简便方法 一个Generator的语法糖
-
作用 使得异步操作更加方便理解和管理
-
async
关键字定义的函数将始终返回一个 Promise 对象,无论该函数是否显式地使用return
语句,之后通过.then() .catch()
对其进行调用。 -
async
函数内部可以包含await
表达式(await
后的对象会被转化为promise
对象),这可以让函数在等待异步操作完成时暂停执行,并且在异步操作完成后恢复执行。函数内部有多个await
.then
函数会等待所有的await
指令运行完的结果才执行内部回调函数 -
在Vue中使用较多
-
案例
//eg1 async function f(){ let s = await 'hello world'; let data = await s.split(''); return data; } f().then(v=>{console.log(v)}).catch(e=>console.log(e));
打印结果
["h","e","l","l","o"," ","w","o","r","l","d"]
//eg2 async function fetchData() { let response = await fetch('https://example.com/data'); let data = await response.json(); return data; } fetchData().then(data => { console.log(data); }).catch(error => { console.error(error); });
定义了一个名为
fetchData
的async
函数。使用await
关键字来等待fetch
函数获取到数据,并且等待 Promise 的response.json()
方法获取到 JSON 数据。由于fetchData
函数声明为async
,它会返回一个 Promise 对象,因此我们可以使用.then()
和.catch()
方法来处理异步操作的结果。
2.12 类class
2.12.1 class介绍
class
是关键字,也一种语法糖,它并没有引入新的面向对象功能,只是提供了更加直观的类定义和继承方式。- 使用 class 关键字可以定义一个类,类名通常采用大写首字母的驼峰命名法,并且可以通过这个类来创建(
new
)对象实例 - 类中的构造函数通过
constructor
方法来定义,它用于初始化新创建的对象实例
2.12.2 造类
-
es5
function Person(name,age){ this.name = name; this.age = age; } Person.prototype.sayName = function(){ return this.name }
-
es6
class Person{ constructor(name,age){ this.name = name; this.age = age; } sayName(){ return this.name } sayAge(){ return this.age } } //通过Object.assign()方法一次性向类中添加多个方法 Object.assign(Person.prototype,{ sayName(){ return this.name }, sayAge(){ return this.age } })
2.12.3 类的继承
-
使用关键字
extends
-
使用
super()
子类可以继承父类的属性和方法 -
子类可以添加自己的属性和方法
-
案例
class Animal{ constructor(species){ this.species = species; } sayName(){ return species; } } class Dog extends Animal{ constructor(species,name,age,color){ super(species);//调用父类的构造函数,继承父类属性和方法 this.name = name; this.age = age; this.color = color; } //子类添加自己的方法 sayAge(){ return `${this.name}有${this.age}岁`; } //子类重写父类方法 sayName(){ return this.name + super.species; } }
2.13 模块化实现
-
历史实现模块化:服务器commonJS 浏览器AMD
-
ES6 module是服务器和浏览器通用的模块解决方案
-
ES6模块功能主要由两个命令构成:
export
和import
-
export
用于规定模块的对外接口 -
import
导入接口用于输入其他模块提供的功能 -
一个模块就是独立的文件,例如nodejs中一个.js文件就是一个模块
-
在VUE REACT等框架里都常用
-
案例
//index.js export const name = 'ddd'; export function sayName(){ return 'ddd'; } const obj = { foo:'foo'; } export default obj;
<body> <script type='module'> import obj,{name,sayName} from './modules/index.js'//obj可以是对象、类,from跟路径 console.log(name,sayName()); // import * as f from './modules/index.js' // console.log(f.default); //直接引入所有 </script> </body>