ES6语法基础

By Cicades

post-cover

ES6常用语法

ES5扩展

对象的扩展

  • 对象方法的扩展

    • Object.create(obj[, options])——以对象为原型创建对象并返回

    • Object.defineProperties(obj1[, options]),为对象添加属性

    var obj = {username: 'hyf', age: 20}
    var obj1 = {}
    obj1 = Object.create(obj, {
      //指定新增的属性
      sex: {
        value: 'male',//指定属性值
        writable: true,//是否可写
        configurable: true,//是否可删除
        enumerable: true//是否可被枚举(遍历)
      }
      })
    
    Object.defineProperties(obj1, {
      fullName: {//新增fullName属性,并添加配置
        get: function () { //obj1.fullName 会默认调用此函数
          return this.firstName + ' ' + this.lastName
        }
        set: function (data) {//obj1.fullName = 'hyf cicades' 会默认调用此函数并将'hyf cicades'作为参数传入
          let name = data.split(' ')//['hyf', 'cicades']
          this.firsName = name[0] //'hyf'
          this.lastName = name[1] //'cicades'
        }
      }
      })
    
    • set functionget function

      类似于上述中settergetter

        let person = {
          fullName: 'cicades hyf',
          get firstName(){
            return this.fullName.split(' ').[0]
          }
          set firstName(data) {
            this.firstName = data
          }
        }
      

1.let 和const命令

2.变量的解构

//基本语法
let [a, b, c] = [1, 2, 3];
//默认值
let [foo = true] = [];
foo // true
let [x, y = 'b'] = ['a']; // x='a', y='b'
let [x, y = 'b'] = ['a', undefined]; // x='a', y='b'
//对象解构
let { foo, bar } = { foo: "aaa", bar: "bbb" };
foo // "aaa"
bar // "bbb"

3.字符串的扩展

  • startsWith()、endsWith(),includes()

  • 字符串可以被for...of遍历

  • repeat(n)——将原字符串重复n次返回

  • 字符串填充

    1. padStart(n,char)——用char进行头部补全,新的字符长度为n
    2. padEnd()
  • 模板字符串

    let x = 1;
    let y = 2;
    
    `${x} + ${y} = ${x + y}`
    // "1 + 2 = 3"
    
    `${x} + ${y * 2} = ${x + y * 2}`
    // "1 + 4 = 5"
    
    let obj = {x: 1, y: 2};
    `${obj.x + obj.y}`
    // "3"
    
  • raw()——对字符串中所有的反斜杠进行转义

4.数值的扩展

  • 数值的判断

    1. Number.isFinite()——是否有限,参数不是数值返回false
    2. Number.isNaN()——是否为数字
  • 数值转型

    1. Number.parseInt()——转整型
    2. Number.parseFloat()——转浮点
    3. Number.isInteger()——是否为整数
  • Math对象的扩展

    1. Math.trunc()——去掉一个数的小数部分,返回整数部分
    2. Math.sign()——判断一个数到底是正数(返回1),负数(返回-1)或者是零(返回0)
    3. Math.hypot(a,b,c)——返回所有参数的平方和的平方根
  • 指数元素符**

    该元素符为右结合性

    // 相当于 2 ** (3 ** 2)
    2 ** 3 ** 2
    

5.函数的扩展

  • 为函数指定默认值

    function log (a, b = 9){
        console.log(a+b);
    }
    log(1)//log:10
    
  • rest参数

    1. 用于获取函数的多余参数,rest参数搭配的变量是一个数组,该变量将多余的参数放入数组中
    2. rest参数后不能使用任何参数
    3. 函数的length属性不包括rest参数,length属性表示,函数参数中没有设置默认值的参数
    funtion add(...values) {
        let sum = 0;
        for (var val of values) {
            sum += val;
        }
        return sum;
    }
    add(2,3,4);
    
  • 箭头函数

    箭头函数自身没有this,所以在箭头函数中使用this,实际上是引用父级对象的this,所以箭头函数的中的“this“在定义时就固定了,判断箭头函数’this’的指向的一个简单方法是,看它定义时是否被包裹在另一个函数内(函数内部会产生跨级作用域),如果有则箭头函数的‘this’和外层保持一致,否则就是‘window ’

    1. 参数 => 返回值
    2. (x1,x2)=>{ return x1 + x2 } ——缺省参数或者定义多个参数时,需要用括号,输出可以用大括号,加return语句

    6.数组的扩展

    • 扩展运算符——... 将数组拆分成参数序列,相当于rest参数的逆运算,适用于函数调用

      //利用扩展运算符求数据中的最大值
      let arr = [11,2,4];
      Math.max(...arr)//11
      //与解构赋值结合起来可以生成数组
      [a,...rest] = [1,2,3,4,5]//rest = [2,3,4,5]
      
    • Array.from(arrayLike,callback)——可以将类似数组的对象转换为数组,并可传入回调函数,有选择的将元素放入数组

    • Array.of(var1,var2,var3)——将一组值转化为数组,这个方法主要弥补数组的构造函数Array()的不足,因为参数个数的不同会导致Array()的行为的差异

    • 数组实例的方法

      1. copyWithin()——在当前数组内部,将指定位置的成员复制到其他位置,然后返回当前数组,此方法会修改当前数组

        //Array.prototype.copyWithin(target,start = 0, end = this.length)
        [1,2,4,5].copyWithin(0,3)//[4,5,4,5]
        
      2. find(callback)——返回第一个使回调函数返回true的元素

        [1,2,3,4,-5].find(x => x < 0)//-5
        //find() 可接受三个参数 value,index,arr  类似于forEach(),只不过forEach()是每个元素执行回调函数
        
      3. findIndex()——与find() 用法一样只不过是用来返回符合条件元素的下标

      4. fill(padEle,start,end)——可以用来填充数组,传入一个参数时,会将数组全部元素的值变为参数的值

      5. entries(),keys(),values()——返回数组中的键值对,索引,值

        for (let index of ['a', 'b'].keys()) {
          console.log(index);
        }
        // 0
        // 1
        
        for (let elem of ['a', 'b'].values()) {
          console.log(elem);
        }
        // 'a'
        // 'b'
        
        for (let [index, elem] of ['a', 'b'].entries()) {
          console.log(index, elem);
        }
        // 0 "a"
        // 1 "b"
        
      6. includes()——查询元素,用法同字符串实例的includes()

      7. flat()——将数组中所有的所有的结构扁平化,即将高维数组转化为低维数组,可以向传入参数控制要展开的层数,类似的方法flatMap(callback)——先过滤元素再执行flat()


7.对象的扩展

  • 属性的简洁表示法,允许直接写入变量

    let name = 'cicades';
    let ob = {name};//等价于 let ob = {name: 'cicades'};
    let ob1 = {printName() {console.log('hello world')}}
    //等价于
    let ob1 = {printName: function() {console.log('hello world')}}
    
  • 方法的name属性

    方法或者函数的name属性可以获得函数或者方法的名字

  • 对象的扩展运算符...

    1. 结构赋值

      let {x, y, ...z} = {x: 1, y: 2, a: 3, b:4}
      //x = 1
      //y = 2
      //z = {a: 3, b:4}
      //结构赋值的拷贝是浅拷贝,对于复合类型的值,解构赋值拷贝的是这个值得引用
      
    2. 扩展运算符

      对象扩展运算符用于取出参数对象得所有可遍历属性拷贝到当前的对象之中

      let z = {a: 3, b: 4}
      let n = {...z}
      n//{a: 3, b: 4}
      //合并对象
      let ab = {...a, ...b}//等价于下列式子
      let ab = Object.assign({}, a, b)
      
    3. in命令

      let obj = {name: 'cicades'};
      'name' in obj // true
      

8.对象的新增方法

  1. Object.is()——比较两个值是否严格相等,类似于===,不同之处为:

    +0 === -0 //true
    NaN === NaN //false
    Object.is(+0, -0) //false
    Object.is(NaN, NaN) //true
    
  2. Object.assign(target, source1, source2)——用于对象合并,将源对象复制到目标对象(target)

    1.Object.assign() 进行的是浅拷贝

    2.源对象的属性值会覆盖目标对象中同名属性的属性值

  3. 返回指定对象所有自身属性Object.getOwnPropertyDescriptors()

    //Object.getOwnPropertyDescriptor() ES5方法,返回指定对象的某个属性的描述对象
    Object.getOwnPropertyDescriptors(obj)//返回指定对象所有自身属性的描述对象,属性名为键
    
  4. 获取/设置对象的原型

    • Object.getPrototypeOf(obj)

      读取指定对象的原型对象

    • Object.setProrotypeof(obj,proto)

      将proto设置为obj对象的原型

  5. 遍历对象

    1. Object.keys(obj)——返回参数对象所有可遍历属性的键名所构成的数组

    2. Object.values()——返回参数对象所有可遍历属性的值所构成的数组

      //参数为字符串时,会返回各个字符组成的一个数组

      Object.values(‘foo’)//[‘f’, ‘o’, ‘o ‘]

    3. Object.entries()——返回参数对象

    4. Object.fromEntries()——Object.entries()的逆操作,用于将一个键值对数组转换为对象

9.Symbol

Symbol是一种新的原始数据类型,表示独一无二的值,它是js中第七种数据类型:null, undefined, string, number, boolean, array, object, Symbol;Symbol的最为属性名,不可被遍历

  • 创建Symbol

    let s = Symbol();//可以为Symbol函数传入一个字符串,用来标识symbol
    typeof s //"symbol"
    
  • Symbol.for(),Symbol.keyFor()

    1. Symbol.for接受一个字符串作为参数,然后搜索有没有以该参数作为名称的 Symbol 值。如果有,就返回这个 Symbol 值,否则就新建并返回一个以该字符串为名称的 Symbol 值。
    2. Symbol.keyFor方法返回一个已登记的 Symbol 类型值的key
    let s1 = Symbol.for('foo');
    Symbol.keyFor(s1)//"foo"
    
    • Symbol的应用
    • 作为对象的属性名(不可被遍历)
    • 定义常量
    • 作为唯一标识(例如:用作jsonp中的唯一的回调函数的函数名)

10.Set和Map数据结构

  • Set

    //Set本身就是一个构造函数,用来生成Set数据结构,类似于数组,但成员的值都是唯一的
    const s = new Set();
    [1,2,3,1,2,3].forEach(x => s.add(x));//add(ele)向Set结构加入成员
    for (let i of s) {
      console.log(i)//1,2,3
    }
    //Set构造函数可接受数组作为参数
    [...new Set(array)]//去除数组中重复的元素
    
  • Set实例的属性和方法

    1. 属性
      • size——返回Set实例的成员总数
    2. 方法
      • add(value)——添加某个值,返回Set结构的本身
      • delete(value)——删除某个值,返回布尔值
      • has(value)——是否拥有某值
      • clear()——清除所有成员,没有返回值
    3. 遍历操作

    keys(), values(), entries(), forEach();set的遍历顺序就是插入时的顺序

  • WeakSet

    WeakSet结构与Set类似也是不重复的值的集合,但WeakSet的成员只能是对象

  • Map

    Map类似于对象,也是键值对的集合,但“键”的范围不限于字符串,各种类型的值都可当作键

  1. 属性和操作方法
    • size——属性,返回Map结构的成员总数
    • set(key,value)——设置键值对,返回整个Map结构
    • get(key)——读取key对应的键值
    • has(key)——判断是否存在key
    • delete(key)——删除某个键
    • clear()——清除所有成员
  2. 遍历方法

    参考Set的遍历方法

  • WeakMap

    WeakMap只接受对象作为成员,WeakMap应用的典型场合就是DOM节点作为键名,将需要与DOM对象绑定的对象作为键值,因为WeakMap对键名进行虚引用,所以当DOM对象内存被回收,WeakMap中对应的键值对也会失效

11.Proxy

Proxy属于一种元编程(meta programming),即对编程程序进行编程;Proxy原意指:代理人;代理物;代表权

  • 应用实例——get(更多拦截方法参考文档)
var person = {
  name: "张三"
};
var proxy = new Proxy(person, {
  get: function(target, property) {
    if (property in target) {
      return target[property];
    } else {
      throw new ReferenceError("Property \"" + property + "\" does not exist.");
    }
  }
});
proxy.name // "张三"
proxy.age // 抛出一个错误

12.Reflect

为对象开发出的一套API

13.Promise

Promise是异步编程的一种解决方案;Promise是一个对象,从它可以获得异步操作的消息;Promise提供统一的API,各种异步操作都可以用同样的方法进行处理

//Promise对象实现Ajax操作
const getJSON = function(url) {
  const promise = new Promise(function(resolve, reject){
    const handler = function() {
      if (this.readyState !== 4) {
        return;
      }
      if (this.status === 200) {
        resolve(this.response);
      } else {
        reject(new Error(this.statusText));
      }
    };
    const client = new XMLHttpRequest();
    client.open("GET", url);
    client.onreadystatechange = handler;
    client.responseType = "json";
    client.setRequestHeader("Accept", "application/json");
    client.send();

  });

  return promise;
};

getJSON("/posts.json").then(function(json) {
  console.log('Contents: ' + json);
  // 如果在此回调函数中返回`promise`对象,即可实现链式编程,即在`then后面`再次调用`then(callback)`
}, function(error) {
  console.error('出错了', error);
});

14.Iterator

  • 模拟Iterator接口

     let myIterator = () => {
      let index = 0
      return {
        next (arr) {
          return {
            value: arr[index++],
            done: arr.length >= index ? false : true
          }
        }
      }
     }
    
  • 已部署Iterator的数据结构或者数据类型

    可以使用for…of..循环遍历】

    • 数组
    • 字符串
    • arguments(伪数组)
    • Set容器
    • Map容器
    • NodeList对象
  • 为对象部署Iterator

    let test = {
      0: 'hell0',
      1: 'world',
      [Symbol.iterator] () {
        let index = 0
        const that = this
        return {
          next () {
          return {
            value: that[index++],
            done: that.length >= index ? false : true
          }
        }
        }
      }
    }
    
  • 为类似数组的对象(以数字为属性值,且存在length属性)部署遍历接口

      let iterable = {
        0: 'a',
        1: 'b',
        2: 'c',
        length: 3,
        [Symbol.iterator]: Array.prototype[Symbol.iterator]
      };
      for (let item of iterable) {
        console.log(item); // 'a', 'b', 'c'
      }
    

15.Generator指针生成器(遍历器生成器)

  • 语法

      let generator = (function* (){
        let v = yield 'hello' //v = 666
        yield 'world'
        return 'haha'
        })()
      generator.next() //{value: 'hello', done: 'false'}
      generator.next(666) //{value: 'world', done: 'false'}
      generator.next() //{value: 'haha', done: 'true'}
    
    
  • 应用

    • 部署Iterator

        let test = {}
        test[Symbol.iterator] = function* () {
          yield 'hello'
          yield 'world'
        }
        for(let v of test) {
          console.log(v)
        }//'hello' 'world'
      
    • 分布发送响应

        //需求:发送news请求之后再发送query
        function getNews(url) {
          $.get(url, function (data) {
              console.log(data)
              let url = 'http://localhost:3000/query'
              SX.next(url) //第二个next 传入url将作为第一次nyield的返回值,请求query
            })
        }
      
        //定义Generator
        function* generator () {
          let url = yield getNews('http;//localhost:3000/news')
          yield getNews(url)
        }
        let SX = generator()
        SX.next() //请求news
      

16.async函数(源自ES2017)

async是generato的语法糖,即是它的升级版

  • 语法

      let test = (ms, value) => {
        return new Promise(resolve => {
          setTimeout(resolve, ms, value)
        })
      }
    
      //使用async 关键字定义async函数
      async function foo() {
        console.log('开始执行 ')
    
         //使用await关键字执行操作,await后面一般跟着promise对象,实现异步操作
         //且await语句的返回值,是其后面的promise对象中为resolve传递的参数
        let value = await test(1000)
    
        console.log('执行结束')
    
         //async函数执行的返回值是promise对象,所以可以使用then进行下一步操作,而它内部使用return返回的值会作为resolve的参数
        return 'hello world'
      }
    
      foo().then(console.log) // 执行结果: 立即输出'开始执行',1s后输出'执行结束'和'hello world'
    

    17.class

    与java类的语法很相似

  • 语法

      class Person {
        //构造函数
        constructor (name, age) {
          this.name = name
          this.age = age
        }
    
        //方法,默认放在原型中
        sayHi () {
          console.log(`I am ${this.name}`)
        }
      }
    
      //定义student类继承person类
      class Student extends Person {
        constructor (name, age, school) {
          super(name, age) //使用super关键字调用父类的构造函数
          this.school = school //添加自己的属性
        }
    
        //方法重写
        sayHi () {
          console.log(`I am ${this.name}, and I am studying in ${this.school}`)
        }
      }
    
      let stu = new Student('cicades', 20, 'ccnu')
      stu.sayHi()
    

18.数据拷贝

  • 常见数据拷贝方法

    • 等号赋值 //浅拷贝
    • Object.assign() //浅拷贝
    • Array.prototype.concat() //浅拷贝
    • Array.prototype.slice() //浅拷贝
    • JSON.parse(JSON.stringify()) //深拷贝
  • 深拷贝

    • 检测数据类型的方法

      • typeof——能够返回的数据类型:String, Null, Object, Undifined, Number, Function
      • Object.prototype.toString.call(data)——能够返回所有数据类型
    • 深度拷贝的实现

        //深拷贝
        //定义一个判断类型的函数
        let check = target => Object.prototype.toString.call(target).slice(8, -1)
        let clone = target => {
          let dataType = check(target)
          let res = null
          if (dataType != 'Array' && dataType !=='Object') {
            res = target
            return res
          }
          if (dataType === 'Array') {
            res = []
          } else if (dataType === 'Object') {
            res = {}
          }
          for (let key in target) {
            //遇到数组、对象则需再次进行clone,函数可以当作简单数据类型
            res[key] = clone(target[key])
          }
          return res
        }