JS高级之ES6+模块化
文章目录
十四、es6内容
可参考阮一峰的ECMAScript 6 入门
14.1 数组API、正则API、字符串API
14.2 模板字符串
- 模板字符串的基本用法
var s1 = `abc`
- 模板字符串的优势:
var obj={ name:"",age:5 };
var s1 ="我叫:"+obj.name+",今年:"+obj.age+"岁。"
14.3 解构赋值
14.3.1 对象的解构赋值
var obj={name:"张三",age:18}
var {name,age}=obj;
//生成2个变量,
// name值来自于obj.name、
// age值来自于obj.age
var {name:title}=obj;
//生成一个变量:title,值来自于obj.name
14.3.2 函数参数的解构赋值
function f1(obj){
console.log(obj.age);
console.log(obj.height)
}
//等价于
function f1({ age,height }){
console.log(age);
console.log(height)
}
f1({age:5,height:180})
14.3.3 补充:属性的简写
var a = 3 ;
var c = 10;
var b = { a,c } ;
//b对象有一个a属性,a属性的值,来自于a变量 ,
//还有一个c属性,c属性的值来自于c变量
console.log(b)
14.4 函数的扩展
14.4.1 rest参数
使用背景:es6的
优点:arguments是伪数组,而rest参数是真数组
function fn(...args){
console.log(args); //数组:[1,2,3,4,5]
}
fn(1,2,3,4,5)
14.4.2 箭头函数
场景:用于替换匿名函数
基本用法:
//匿名函数
div.onclick=function(){
console.log("你好")
}
//箭头函数
div.onclick=()=>{
console.log("你好")
}
有一个参数的箭头函数
var fn=(a)=>{
console.log("abc");
}
//等价于:
var fn=a=>{
console.log("abc");
}
有2个及更多参数的箭头函数
var f=(a,b,c)=>{
console.log("abc")
}
箭头函数和普通匿名函数有哪些不同?
- 函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
- 不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
- 不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。
- (不常用)不可以使用yield命令,因此箭头函数不能用作 Generator 函数。
- generator函数现在经常用async替代
14.5 对象的扩展
- Object.assign:实现拷贝继承
- 对象扩展运算符
var obj1={ age:5,gender:"男" }
var obj2={ ...obj1 }
var obj3={ ...obj1 , age:10 }
14.6 Promise
为什么要有promise:解决回调地狱的问题
14.6.1 回调地狱:
//跟以前的if条件地狱很像
// if(){
// if(){
// if(){
// }
// }
// }
$.get("/getUser",function(res){
$.get("/getUserDetail",function(){
$.get("/getCart",function(){
$.get("/getBooks",function(){
//...
})
})
})
})
//node开发:读取文件;开个服务器、接收一个请求、请求路径、访问数据库
14.6.2 Promise函数基本用法
var promise=new Promise((resolve,reject)=>{
//b 把需要执行的异步操作放在这里
$.get("/getUser",res=>{
//获取数据的异步操作已经执行完毕了,等待下一步的执行,通过执行resolve函数,告诉外界你可以执行下一步操作了
//c、
resolve(res)
//而执行的下一步操作,其实就是写在then的回调函数中的
})
})
//a、
promise.then(res=>{
//d、执行后续的操作
console.log(res);
})
14.6.3 Promise函数实现多层回调
new Promise((resolve,reject)=>{
$.get("/getUser",res=>{
resolve(res)
})
}).then(res=>{
//用户基本信息
return new Promise(resolve=>{
$.get("/getUserDetail",res=>{
resolve(res)
})
})
}).then(res=>{
//用户详情
return new Promise(resolve=>{
$.get("/getCart",res=>{
resolve(res)
})
})
}).then(res=>{
//购物车信息
})
14.6.4 Promise函数错误处理
方式一
new Promise((resolve,reject)=>{
$.ajax({
url:"/getUser",
type:"GET",
success:res=>{
resolve(res);
},
error:res=>{
reject(res)
}
})
}).then(resSuccess=>{
//成功的返回值
},resError=>{
//失败的返回值
})
方式二:
new Promise((resolve,reject)=>{
$.ajax({
url:"/getUser",
type:"GET",
success:res=>{
resolve(res);
},
error:res=>{
reject(res)
}
})
}).then(resSuccess=>{
//成功的返回值
}).catch(resError=>{
//失败的返回值
})
14.7 async
async其实是一个promise的语法糖
async function get(){
console.log('开始执行');
var res = await timer()
console.log('执行结束:',res);
}
function timer(){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve("你好");
},1000)
})
}
get();
- await可以执行异步操作,但是await必须在async函数内执行
- await操作可以有返回值,这个返回值表示promise操作成功的返回值
- 如果await里面执行的异步操作发生了reject,或者发生了错误,那么只能使用try…catch语法来进行错误处理
14.8 generator
Generator是ES6的新特性,通过yield关键字,可以让函数的执行流挂起,那么便为改变执行流程提供了可能。
14.9 class
14.9.1 定义一个类
class Person {
constructor(name) {
this.name=name;
}
}
//相当于:
function Person(name){
this.name=name;
}
14.9.2 添加实例方法
class Person {
constructor(name,age) {
this.name=name;
this.age=age;
}
//定义方法
say() {
console.log("大家好,我叫:"+this.name+",今年:"+this.age+"岁");
}
travel(){
console.log("坐着飞机去巴厘岛");
}
}
14.9.3 添加静态方法
- 静态成员:静态属性、静态方法
- 静态属性:通过类本身来访问:Person.maxAge
- 静态方法:通过类本身来访问的一个方法:Person.born();
class Animal {
constructor(){
}
static born(){
console.log("小呆萌出生了")
}
}
//访问静态方法
Animal.born();
14.9.4 类的继承
//父类
class Person {
constructor(name){
this.name=name;
}
}
//Student类继承自Person类
class Student extends Person {
//构造方法
constructor(name,grade){
//规定:必须调用父类构造方法,如果不调用就会报错
super(name);
//调用父类构造方法,从而给子类的实例添加了name属性
this.grade=grade;
}
}
[1,3,5].map(function(value,index){})
[1,3,5].map((value,index)=>{})
//以前变量和字符串拼接,现在用模板字符串
14.10 module
14.10.1 浏览器调试
本地调试,会受浏览器同源策略的影响,需要开启web服务才能打开
<script type="module">
//导入模块
</script>
14.10.2 基本用法
导出模块:
//common.js
export default { name:"abc" }
导入模块:(
//b.js
import common from "common.js"
console.log( common.name ) //"abc"
14.10.3 模块有多个导出
//person.js
export const jim = { country :"France" }
export const tony = { color:"gray" }
//默认的导出
export default { name:"abc" }
//index.js
import person , { jim , tony } from "person.js"
//person:{ name:"abc" }
//jim:{ country :"France" }
//tony:{ color:"gray" }
14.10.4 模块导入导出取别名
//person.js
export const tony = { color:"gray" }
export { tony as Tony }
//index.js
import { Tony } from "person.js"
import { Tony as man} from "person.js"
console.log(man) //{ color:"gray" }
十五、模块化
15.1 非模块化的弊端
- 代码杂乱无章,没有条理性,不便于维护,不便于复用
- 很多代码重复、逻辑重复
- 全局变量污染
- 不方便保护私有数据(闭包)
15.2 基本实现:闭包的自调用函数
//日期控件
var DatePicker = (function(){
return {
init(){}
}
})();
//Header
// tabbar
// login
//Content
// sidebar
// table
//Footer
var KTV=(function(){
return {
pay(){},
xiaofei(){}
}
})()
15.3 AMD模块化 -->requireJS
- AMD:async module define:异步模块定义
- AMD其实就是requireJS实现的模块化解决方案
15.4 其他模块化解决方案:
- CommonJS:Node中使用的模块化解决方案
- CMD(common module define):seajs中提出来的模块化解决方案
- 其实CMD可以认为是CommonJS的前端实现
- seajs由阿里的(玉帛)编写
- seajs在2,3年前比较火,从去年开始已经停止更新
- vue 、angular、react已经集成了各自的模块化
- es6模块化
- webpack也有模块化的解决方案
15.5 AMD和CMD的不同之处
- amd需要依赖前置,cmd需要依赖就近
- 导入导出方式不同:
- amd通过define定义,return导出;
- cmd通过不需要定义,只需要最后通过module.exports、exports导出
15.6 requireJS —— AMD规范
15.6.1 基本用法
//1、通过script标签导入requirejs源文件
//2、编写模块文件,基本格式如下:
//home.js
define([],function(){
console.log('home模块');
})
//user.js
define([],function(){
console.log('user模块');
})
//3、首页调用模块:
require(["home","product.js"],function(){ })
15.6.2 入口文件
15.6.3 配置
require.config({
baseUrl:'js',
paths:{
'jquery':'jquery.min.js',
}
})
15.6.4 定义模块的返回值(返回值相当于模块的入口)
//user.js:
define([],function(){
return {
init(){},
addUser(){}
}
})
//首页:运行时加载
require(["cart"],function(cart){
cart.init();
cart.addUser();
})
注意:一般在导入模块的时候,需要将有返回值的模块
在[前面]
导入,无返回值的模块
在[后面]
导入
15.6.5 案例——模块依赖子模块
//userAdd.js
define([],function(){
return {
init(){
console.log("添加用户");
}
}
})
//userEdit.js
define([],function(){
return {
init(){
console.log("编辑用户");
}
}
})
//user.js define(["userAdd","userEdit"],function(userAdd,userEdit){
return {
init(){
console.log("用户初始化");
},
add(){
userAdd.init();
},
edit(){
userEdit.init();
}
}
})
//首页:
require(["user"],function(user){
user.init();
user.add();
user.edit();
})
15.6.7 检测第三方库是否支持AMD规范
if ( typeof define === "function" && define.amd ) {
define([], function() {
return jQuery;
} );
}
类似的还有:echarts
15.6.8 常用的模块、文件夹路径的配置
一般用于配置第三方模块,比如jquery、bootstrap、zepto等等
require.config(
paths:{
jquery:"js/lib/jquery-1.11.min",
zepto:"js/lib/zepto.min",
bootstrap:"assets/bootstrap/js/bootstrap.min"
}
)
define(["jquery","zepto"],function($,$$){})
require(["jquery","bootstrap"],function($){})
15.6.9 插件
- 插件列表:
https://github.com/requirejs/requirejs/wiki/Plugins
- i18n 国际化
- text 加载文件(.html文件。。。)
- 插件github地址:https://github.com/requirejs/text
15.6.10 requirejs解决循环依赖
- a已经依赖了b
- b中先添加require模块的依赖,然后再添加a的依赖,但是并不要去通过回调函数的形参获取返回值
define(["require","a"],function(require){})
- 在需要执行a模块代码的时候,
require("a")()
15.6.11 requirejs和vuejs浅显的比较
- requirejs是一个库
- 功能:只是一种模块化的解决方案
- vue是一个框架
功能:- 1、不仅仅是模块化的解决方案
- 2、减少了DOM的操作(–>jquery的功能)
15.6.12 node中的模块化
- require(“http”).createServer()
- require(“fs”).readFile()
- require(“common/type”).doSth()
15.6.13 前端路由的意义
- 1、通过路由将各个功能从url上面就分辨出来了
- /user/list
- /user/3
- /user/edit/3
- 2、路由还可以进行前进、后退等导航操作
15.6.14 前端路由的实现方式
- 1、监听window对象的hashchange事件
- hash值:通过location.hash获取,获取的值以
#
开头 - 也可以通过location.hash来设置hash值,当然设置的新hash也应该以
#
开头
- hash值:通过location.hash获取,获取的值以
- 2、history对象:popState/pushState