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规范

requireJS中文网

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文件。。。)

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也应该以#开头
  • 2、history对象:popState/pushState
posted @ 2019-05-23 16:25  南山道士  阅读(114)  评论(0编辑  收藏  举报