es6

头像
kaze
    阅读 12 分钟

    ES6

    一、变量

    1.1 let变量

    用于声明变量,用法与var类似,但存在新的特性

    特性:

    • let所声明的变量,只在当前代码块内有效,避免全局污染
    • 没有变量声明提升
    • 暂时性死区,在let命令声明变量前,该变量都是不可用的
    • 不允许重复声明

    二、常量

    2.1 const命令

    用于声明常量

    特性

    • 不可以重新赋值

      const obj = {
          name:'alice',
          age:22
      }
      obj.name = 'zhang'            //{ name: 'zhang', age: 22 },不报错,因为只改变了对象的值,没有改变引用地址
    • 声明的同时必须初始化

      const a = 7;
    • 暂时性死区
    • 不允许重复声明
    • 只在当前的代码块内有效

    三、解构

    3.1 数组解构

    • 从数组和对象中提取值,对变量进行赋值。即只要等号两边的模式相同,等号右边的值就会一一进行赋值。

      let [a,b,c] = [1,2,3]
      let [a,b,c] = [1,2,3,4]            //1 2 3
      let [a,b,...c] = [1,2,3,4]            //1 2 [3,4]
      let[a,b,c,d,e] = [1,2,3]            //1 2 3 undefined undefined
      //等号左边变量多余,多余的变量会被赋值为undefined
      //等号右边变量多余,多余的变量会被忽视或者使用...将其整合为一个数组
      let[a,[b],c] = [1,[2,3],4]            //1 2 4
      let[a,b,c] = [1,[2,3],4]            //1 [ 2, 3 ] 4
      let[a,[b,c],d] = [1,[2,3],4]        //1 2 3 4
      let[a,b,c,d] = [1,[2,3],4]            //1 [ 2, 3 ] 4 undefined
      let[a,b=22] = [10]                    //10 22
      let[a,b=22] = [10,20]                //10 20
      //如果改变了默认值,则以改变后的值为准,若没有改变,则继续使用默认值
    • 数组嵌套对象

      let[a,{name:user}] = ['hello',{name:'tom'}]
      console.log(a, user)
      //hello tom
    • 对象嵌套数组

      let{test} = {test:[1,2,3]}
      console.log(test)
      //[1,2,3]
    • 默认值可为函数

      function f(){console.log(111)}
      let[x=f()] = [1]
      console.log(x)                     //1

    3.2 对象解构

    • 对象的属性没有次序,所以变量必须与属性同名,才能取到正确的值

      let{name,age} = {name:'tom',age:12}
      //是let{name:name,age:age} = {name:'tom',age:12}的简写
      console.log(name,age)            //tom 12
    • //若要修改属性名
      let{foo:bar}={foo:'ss',bar:'aa'}//将foo改为bar,bar的值为'ss'
      console.log(bar)                //ss

    3.3 字符串解构

    • 字符串被转换成一个类似数组的对象

      const [a, b, c, d, e] = ‘hello’;    
      //a=h;b=e;c=l;d=l;e=o
    • 对数组的属性解构

      let{length:t}='zzzh'
      console.log(t)            //4
      let{trim}='zzz'
      console.log(trim === String.prototype.trim)        //true
      //可以解构其原型上的方法
      let{toString}=true
      console.log(toString === Boolean.prototype.toString);            //true
    • 函数参数解构

      function test([a,b]){
          return a+b
      }
      let res  = test([1,2])
      console.log(res)                //3
      
      function test({a=3,b=2}){
          return a*b
      }
      let s = test({a:1})
      console.log(s)                    //2

    用处

    • 从函数返回多个值

      function foo(){
          return[1,2,3]
      }
      let[a,b,c] = foo()
    • 交换变量的值

      let a=3;
      let b=4;
      [a,b]=[b,a];

    四、对象扩展

    • ES6允许直接在对象中写入变量和方法,此时属性名就是变量名,属性值就是变量值

      let name = 'tom'
      let age = 12
      // let obj = {
      //     name:name,
      //     age:age,
      //     gender:'男',
      //     sayName:function(){
      //         console.log(1111)
      //     }
      // }
      let obj = {
          name,
          age,
          gender:'男',
          sayName(){
              console.log(1111)
          }
      }
    • 方法的name属性为方法名

      function test(){}
      console.log(test.name)            //test
      
      let p = {
          //test:function(){}
          test(){
      
          }
      }
      console.log(p.test.name)        //test
    • let test = 'hello'
      let obj = {
          name:'zhangsan',
          //test:'hello'
          test,
      [test]:'123'

    }
    console.log(obj) //{ name: 'zhangsan', test: 'hello', hello: '123' }

    
    - Object.is()用来判断两个值是否相等,与===的不同之处:-0不等于+0,NAN相等
    

    let a = +0
    let b = -0
    var res = Object.is(a,b) //false
    console.log(a===b) //true

    let a = NaN
    let b = NaN
    var res = Object.is(a,b)
    console.log(a===b) //false
    console.log(res) //true

    
    - Object.assign(target,...,obj)将后面的参数对象合并到target对象中,是一种浅拷贝
    

    let obj1={

      name:'tom'

    }
    let obj2 = {

      name:'zhangsan',
      age:12

    }
    let obj3 = {

      gender:'男',
      sayName:function(){
    
      }

    }
    let target = {}
    let res = Object.assign(target,obj1,obj2,obj3)
    console.log(target)
    console.log(res)
    /*上下返回一致{

    name: 'zhangsan',
    age: 12,
    gender: '男',
    sayName: [Function: sayName]

    }*/

    
    自己写assign函数
    

    function myAssign(target,...temp){

      temp.forEach(function(item){
          for(var key in item){
              target[key] = item[key]
          }
      })
      return target

    }
    myAssign(target,obj2,obj1,obj3)
    console.log(target)
    //{ name: 'tom', age: 12, gender: '男', sayName: [Function: sayName] }

    
    - Object.keys(obj) 返回由obj对象的属性名构成的一个数组
    
    Object.values(obj) 返回由obj对象的属性值构成的一个数组
    
    Object.entries(obj) 返回由obj对象中属性名和属性值组成的数组所构成的数组
    

    let obj = {

      name:'ss',
      age:13,
      gender:'女'

    }
    var res = Object.keys(obj)
    console.log(res) //[ 'name', 'age', 'gender' ]
    var res = Object.values(obj)
    console.log(res) //[ 'ss', 13, '女' ]
    var res = Object.entries(obj)
    console.log(res) //[ [ 'name', 'ss' ], [ 'age', 13 ], [ 'gender', '女' ] ]

    
    ## 五、函数扩展
    
    - 允许为函数的参数设置默认值(函数的length属性值为未给予默认值的参数个数)
    
    - rest参数(...变量名)
    

    function foo(...values){

      console.log(values)

    }
    foo(1,2,3,2,1) //[ 1, 2, 3, 2, 1 ]

    
    - **箭头函数**
    
    - ```javascript
      let test1 = (a,b)=> console.log(a+b)
      test1(1,2)
      let test2 = a => console.log(a)
      test2(1)
      //参数只有一个时可以省略小括号(),函数体中只有一条语句时可以省略大括号{}
    •   //箭头函数没有自己的this,而是引用外部的this
        let obj = {
            name:'tom',
            sayName(){
                console.log(this)
            }
        }        
        obj.sayName()                        //{ name: 'tom', sayName: [Function: sayName] }
        
        let obj = {
            name:'tom',
            sayName:()=>{
                console.log(this)
            }
        }
        obj.sayName()                        //{}
        //此时的this指向全局
    • 不能作为构造函数
    • 没有内部属性arguments

    五、数组扩展

    • 扩展运算符(..),rest参数的逆运算

      let arr =[1,2,3]
      console.log(...arr)            //1 2 3
      console.log([...'hello'])        //[ 'h', 'e', 'l', 'l', 'o' ],即将字符串转换为数组
    • Array.from() 可以将类数组对象或可迭代数据转换成数组

      let obj = {'0':'hello','1':'world','2':'nice',length:5}
      console.log(Array.from(obj))        //[ 'hello', 'world', 'nice', undefined, undefined ]
    • Array.of() 可以将一组值转换成数组

      console.log(Array.of(true,true,false))                 //[ true, true, false ]
      console.log(Array.of('hello','nice','world'))            //[ 'hello', 'nice', 'world' ]
    • .find() 参数是一个回调函数,所有数组成员依次执行此回调函数,直到找到第一个被回调函数筛选出的值(即第一个返回值为true的成员),并返回该值

      let arr = [10,2,3,,11]
      let res = arr.find((item,index,arr)=>{
          return item<10
      })
      console.log(res)    //2
      //若没有符合条件的值,则返回undefined

      .findIndex() 遍历数组,找到第一个被回调函数筛选出的值,并返回该值的索引

      let arr = [10,2,3,,11]
      let res = arr.findIndex((item,index,arr)=>{
          return item<10
      })
      console.log(res)                //1
      //若没有符合条件的值,则返回-1
    • .fill() 使用固定的值去填充数组

      let arr = []
      arr.length = 3
      let res = arr.fill(10)
      console.log(res)            //[10,10,10]
      console.log(res === arr)    //true
    • .keys(),values(),entries(),返回一个遍历器对象,可执行for-of命令进行遍历

      索引,值,键值对

    • .includes() 判断某个数是否存在于数组中,返回一个布尔值

    六、Set/Map

    6.1 Set

    类似于数组,但它的数据集合是无重复的

    //s是Set的实例
    arr = [1,2,2,1,2,3,4,5]
    let s = new Set(arr)
    console.log(s)            //Set { 1, 2, 3, 4, 5 }
    arr = [...s]            //将set对象转换为数组
    console.log(arr)        //[1,2,3,4,5]
    • 属性:

      .size Set实例中的成员总数

    • 方法:

      .add(value) / .delete(value) / .clear() / .has(value) set成员中是否包含该值 / .forEach() / .keys(),values(),entries()

    • s = [1,1,1,2,3,4,1]
      console.log([...new Set(s)])        //去重,参数可以为具有iterator接口的其他数据结构

    6.2 Map

    Map类似于对象,也是键值对的集合,但是其键的数据类型不仅限于字符串

    //可以接收数组作为参数
    let map = new Map([ ['name', '张三'], ['title', 'Author'] ]);
    console.log(map)                //Map { 'name' => '张三', 'title' => 'Author' }
    map.set('name','alex')
    map.set('age',12)
    console.log(map.has('age'))
    map.delete('name')
    • 属性:

      .size Map结构中的成员总数

    • 方法:

      .set(key,value) / .get(key) / .delete(key) / .clear() / .has(key) Map对象中是否包含该键 / .forEach() / .keys(),values(),entries()

    6.3 Iterator(遍历器)

    Iterator是一种接口,为各种不同的数据结构提供统一的访问机制。任何只要被部署Iterator接口的数据结构都可以完成遍历操作。

    • 作用:

      • 为各种数据结构提供了统一的、简便的访问接口
      • 使得数据结构的成员能够按某种次序排列
      • 供es6新推出的遍历命令for...of消费

        let arr = [1,2,3,4,5]
        let keys = arr.keys()
        for(let key of keys){
            console.log(key)
        }
    • 具备Iterator接口的数据结构:

      Array、Map、Set、String、TypeArray、函数的arguments对象、NodeList对象

    • next()

      let s = new Set([10,2,2,2,3,1])
      let values = s.values()
      console.log(values.next())  //{ value: 10, done: false }false代表没有结束
      console.log(values.next())  //{ value: 2, done: false }
      console.log(values.next())  //{ value: 3, done: false }
      console.log(values.next())  //{ value: 1, done: false }
      console.log(values.next())  //{ value: undefined, done: true }

    七、Class

    ES6的class中的绝大多数功能ES5都能做到,新的class写法只是让对象原型的写法更加清晰更像面向对象编程的语法。

    class Animal{
        //构造函数
        constructor(name){
            this.name = name        //类的实例属性定义在构造函数当中
        }
        //在类中可以直接定义方法,这些方法都定义在类的prototype属性上面,都会被实例继承。
        toSay(){
            console.log('实例方法')
        }
        //静态方法不能被实例调用(继承),只能通过类调用
        //静态方法中的this指的是类,而不是实例
        static mySay(){
            console.log('静态方法')
        }
    }
    let cat = new Animal('tom')
    cat.toSay()
    Animal.mySay()
    console.log(cat)
    //静态属性只能通过此种方法进行定义
    Animal.sound = 'miao'
    console.log(Animal.sound)        //miao
    
    //可以通过Object.assign()方法向类的原型中添加方法
    Object.assign(Point.prototype, { 
        toString(){}, 
        toValue(){} 
    });

    继承

    class Animal{
        constructor(name){
            this.name = name;
        }
        say(){
            console.log('say')
        }
        static sayMy(){
            console.log('sayMy')
        }
    }
    class Dog extends Animal{
        constructor(name,age){
            //此时的super()相当于Animal.prototype.constructor.call(this),即调用父类的构造函数(this指向的的是Dog,返回的是Dog的实例)
            //此时的super为函数
            super(name);
            this.age = age;
        }
        Dogsay(){
            //super指向父类的原型对象,相当于super.say.call(this),this指向Dog
            //此时的super为对象
            super.say()
        }
        static DogsayMy(){
            //super指向父类
            super.sayMy()
        }
    }
    let dog = new Dog('wang',6)
    dog.say()
    dog.Dogsay()
    Dog.sayMy()
    Dog.DogsayMy()
    console.log(dog)
    console.log(Dog.__proto__ === Animal)
    //子类的__proto__属性表示构造函数的继承,指向父类
    console.log(Dog.prototype.__proto__ === Animal.prototype)
    //子类的prototype.__proto__属性表示方法的继承,指向父类

    八、Promise

    Promise是一个容器,存放着未来将要结束的某个事件(通常是异步操作)的结果。同时,Promise也是一个对象,可以获取异步操作的消息。它可以将异步操作以同步操作的流程表达出来。用于解决异步,优化异步。

    promise的参数是一个函数,函数的参数分别为resolve和reject:

    • resolve函数在异步操作成功时调用(promise对象的状态pedding-->fullfilled),会将异步操作的结果,作为参数传递给回调函数
    • reject函数在异步操作失败时调用(promise对象的状态pedding-->rejected),会将异步操作报出的错误,作为参数传递给回调函数

    通过then方法和catch方法(或者then方法的第二个参数,一般不使用)分别指定两个状态的回调函数

    let p = new Promise((resolve,reject)=>{
        $.ajax({
            url:'http://39.105.67.242:5588/orde/findAll',
            method:'get',
            success:function(res){
                resolve(res)
            },
            error:function(e){
                reject(e)
            }
        })
    })
    
    p.then((res)=>{
        console.log(res)
    }).catch((e)=>{
        console.log(e)
    }).finally(()=>{
        //不管Promise的状态最后如何,都会执行此回调函数
        console.log('结束')
    })
    • Promise.all()

      //参数为一个数组,p1,p2,p3都为Promise实例
      var p = Promise.all([p1,p2,p3])

      只有p1,p2,p3的状态都转变为fullfilled,p的状态才能转变为fullfilled。此时p1,p2,p3的返回值组成一个数组,传递给p的回调函数。p1,p2,p3中只要有一个状态转变为rejected,p的状态就转变为rejected,此时第一个状态变为rejected的实例的返回值被传递给p的回调函数。

    • Promise.race()

      //参数为一个数组
      var p = Promise.race([p1,p2,p3])

      只p1,p2,p3中有一个实例的状态被改变,p的状态就会被改变。率先改变状态的实例的返回值被传递给p的回调函数。

    九、Generator

    Generator是一个状态机,封装了多个内部状态。执行Generator函数会返回一个遍历器对象,可以依次遍历Generator函数内部的每一个状态。

    可以将异步操作同步化。

    //function与函数名之间加*
    function* test(){
        yield 'hello'
        yield 'world'
        yield 'nice'
        return 'yes'
    }
    let res = test()    //返回一个迭代器对象
    console.log(res.next()) //{ value: 'hello', done: false }
    console.log(res.next()) //{ value: 'world', done: false }
    console.log(res.next()) //{ value: 'nice', done: false }
    console.log(res.next()) //{ value: 'yes', done: true }

    应用:

    let axios = require('axios')
    function* main() {  
        var result = yield request("http://39.105.67.242:5588/customer/findAll");  
        console.log(result.data);
    }
    function request(url) {  
        // response参数当做上一个yield表达式的返回值
        //.then代表异步请求成功
        axios.get(url).then(function(response){it.next(response);});
        //it.next(response)执行的是result=response以及后面的输出语句
    }
    var it = main();//返回迭代器对象
    it.next();//执行yield表达式里的request函数

    十、Async

    将异步操作同步化

    let axios = require('axios')
    //function前加async
    async function foo(){
        //只有当前的异步操作完成后,才能执行下面的输出操作
        let customers = await axios.get("http://39.105.67.242:5588/customer/findAll");
        console.log("customers:",customers.data.data[0].id);        
    }                
    foo();

    十一、模块化

    CommonJS API将通过定义处理许多常见应用程序需求的API来填补javascript规范没有定义用于构建更广泛应用程序的标准库的缺点,最终提供与Python、Ruby和Java一样丰富的标准库。其意图是应用程序开发人员能够使用CommonJS API编写应用程序,然后在不同的JavaScript解释器和主机环境中运行该应用程序。

    11.1 模块化作用域

    每个文件就是一个模块,有自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见.

    • 全局属性

      global.warn = true
    • 私有属性

    11.2 模块的导入导出(模块交互)

    • CommanJS

      • 导出(定义模块)

        //module变量代表当前模块,其exports属性是对外的接口
        module.exports.a = a
      • 导入(模块加载)

        let b = require('模块路径')
        console.log(b.a)
    • es6

      • 导出

        export default xx
      • 导入

        import xx from ''

    11.3 模块对象

    • module.id 模块的识别符,通常是带有绝对路径的模块文件名。
    • module.filename 模块的文件名,带有绝对路径。
    • module.loaded 返回一个布尔值,表示模块是否已经完成加载。
    • module.parent 返回一个对象,表示调用该模块的模块。
    • module.children 返回一个数组,表示该模块要用到的其他模块。
    • module.exports 表示模块对外输出的值。

    11.2 path模块

    用于文件路径

    • 安装path模块

      npm install path
    • 引入path模块

      var path = require('path')
    • basename('') 返回文件名
    • dirname('')返回目录名
    • extname('')返回文件扩展名
    let path = require('path')
    console.log(path.basename('./a.js'))    //a.js
    console.log(path.dirname('d:/briup/4-es6/0821/a.js'))    //d:/briup/4-es6/0821
    console.log(path.extname('./a.js'))        //.js

    11.3 querystring模块

    • 把对象转换成查询字符串

      let res = querystring.stringify(obj)
    • 把查询字符串转换成对象

      let str = querystring.parse(res)

    十二、npm

    Npm是使Js开发者能够更方便的分享和复用以及更新代码,被复用的代码被称为包或者模块,一个模块中包含了一到多个js文件。在模块中一般还会包含一个package.json的文件,该文件中包含了该模块的配置信息。一个完整的项目,需要依赖很多个模块。

    • > npm init  

      创建配置文件package.json

      > npm init -y

      创建默认配置文件

    • > npm install npm@latest -g

      更新npm(npm会随着node一起被安装到本地)

    • > npm install -g cnpm --registry=https://registry.npm.taobao.org

      安装淘宝镜像,加快下载速度

    • > npm install + '依赖的名字' 

      安装模块,安装模块时,默认会将所安装的模块写入到package.json中的dependencies属性中。如果想要仅在当前模块中使用某个第三方模块,就可以使用npm install的默认安装,默认安装即是本地安装;如果想要在命令行中使用模块,就需要进行全局安装。

      > npm install

      安装所有项目依赖的模块(依赖关系在配置文件中已存在)

    • > npm update <module_name>

      更新模块

    • > npm uninstall -g <package_name>

      从node_modules中删除不需要的模块

      > npm uninstall –save -g <package_name>

      不仅删除node_modules中的依赖,还需要删除package.json中的信息,可以使用—save参数

    • -g 全局安装,一处安装处处使用,不加-g,即为局部安装,只在当前路径内有效

    十三、babel

    babel用于将es6转换成浏览器可识别的es5(因为浏览器只能识别一部分es6的语法)

    • > babel a.js
      //将a.js代码转换为es6
    • > babel a.js --out-file test.js  
      //将a.js的代码转换成es5并导入到test.js文件中
    • babel src --out-dir srcc
      //将src文件夹中所有的文件转换为es5并导入到srcc文件夹下

    kaze
    1 声望1 粉丝

    下一篇 »
    jQuery

    引用和评论

    0 条评论