• es678910语法糖


    傲娇:
    新es是js的进步,是编程的进步,es6已经过去了5年了,兼容率达到了90%,还是有10%的手机不兼容,那到底应不应该去照顾那些跟不上的人,我觉得是不应该的,新es能5行写出来的功能,我为什么要用旧的写50行,还那么难理解,难维护,但我还是兼容了,人在屋檐下,不得不低头

    Label是es向下兼容的工具,这个在node分类下提及,这里不说

    所有的内容都来自 阮一峰大神的博客
    2019年11月09日中午12点,博客里的内容从【0前言到31参考链接】
    经常用的api有

    • let和const
    • 解构赋值 和 拓展运算符
    • 字符串拓展
    • 数字的拓展
    • 函数的拓展 和 拓展运算符
    • 数组的拓展 和 Iterator
    • 对象的拓展
    • 新类型Set 和 Iterator
    • 新类型Map 和 Iterator
    • Reflect
    • Proxy观察者
    • Promise
    • async
    • class
    • module

    let和const

    • let代替了var,let没有变量提升,也可以理解为解析js代码流程中,遇到let会自动跳过,在执行过程中才能识别
    • const不是变量,而是固定常亮,如果是基础数据类型第一次赋值后不能被修改值,如果是复杂数据类型,可以修改内部的内容,但是不能修改数据类型,而且一个函数作用域里只能声明一次,也就是不能声明两次aa,会报错,能保护这个值不轻易被另一个程序员重新声明或者改了
      还有些详细内容放在下一篇写

    解构赋值
    解构赋值分为数组解构和对象解构

    数组解构,是按顺序来的,并且左边用数组解构,右边一定要是数组

    // 基础应用
    // 可以理解为右边的数组是ajax请求来的res
    let [a, b, c] = [1, 2, 3];
    console.log(a,b,c)
    
    // 跳过使用
    let [ , , c] = ["foo", "bar", "baz"];
    console.log(c)  // "baz"
    
    // 二级数组
    let [a, b, d] = [1, [2, 3], 4];
    console.log(b)  //[2,3]
    
    // 拓展运算符
    // 拓展运算符一次赋值只能用一次,而且只能用在最后一位
    let [head, ...tail] = [1, 2, 3, 4];
    head // 1
    tail // [2, 3, 4]
    

    对象解构
    对象解构是用key赋值的,没有顺序
    对象解构比数组解构用得多得多

    // 基础应用
    // 可以理解为右边的数组是ajax请求来的res
    let { bar,foo,ceshi} = { foo: 'aaa', bar: 'bbb' };
    console.log(bar,foo,ceshi)  // 'bbb','aaa',undefined
    
    // 上面的写法其实是对象的省略写法,因为key-value同名所以缩写
    // 如果不缩写是 let { bar:bar,foo:foo,ceshi:ceshi} = { foo: 'aaa', bar: 'bbb' };
    // 所以不缩写可以重命名
    let { bar:newBar,foo:newFoo,ceshi:newCeshi} = { foo: 'aaa', bar: 'bbb' };
    console.log(newBar,newFoo,newCeshi)  // 'bbb','aaa',undefined
    
    // 默认值
    var {x = 1} = {};
    console.log(x) //1
    
    // 上面的默认值也是省略写法
    var {x:newX = 1} = {x: 5};
    console.log(newX) //5
    
    //清除对象里不要的key
    let {_internal, tooBig, ...cleanObject} = {el1: '1', _internal:"secret", tooBig:{}, el2: '2', el3: '3'};
    console.log(cleanObject); // {el1: '1', el2: '2', el3: '3'}
    

    字符串拓展
    上代码自己理解

    var basket = {
       count: 10,
       onSale: "aa"
    }
    // 原先的字符串拼接
    $('#result').append(
      'There are <b>' + basket.count + '</b> ' +
      'items in your basket, ' +
      '<em>' + basket.onSale +
      '</em> are on sale!'
    );
    
    // 新版的字符串拼接,两端是``斜点
    // 数据是${...},
    // 可以用默认值 ${ name || "pdt" }
    // 可以用简单的方法${ time2date(time) }
    $('#result').append(`
      There are <b>${basket.count}</b> items
       in your basket, <em>${basket.onSale}</em>
      are on sale!
    `);
    

    数字的拓展
    之前把字符串转数字用的是减零

    Number("123")
    
    // 转不了的就是NaN
    Number("123a")  //NaN
    

    函数的拓展
    有参数默认值,参数解构,参数拓展运算符,箭头函数

    // 参数默认值
    // 以往的参数默认值是这样的
    function init(name){
       var name = name || "pdt"
    }
    
    // es6可以
    function init(name = "pdt"){ ... }
    
    // 参数解构
    // 老版本
    function init(arr,obj){ ... }
    init([1,2],{name:"pdt",age:18})
    
    // 新写法
    function init([,b],{name="无名"}){
       //比如我只需要数组的第二个和name属性
       console.log(a,b,name)
    }
    init([1,2],{name:"pdt",age:18})
    
    //参数必填
    const required = () => {throw new Error('Missing parameter')};
    const add = (a = required(), b = required()) => a + b;
    add(1, 2) //3
    
    // 箭头函数,是function的缩写
    // 但是不能作为对象的value,不能作为数组的值,不能作为构造函数
    // 箭头函数没有自己的this
    // 箭头函数没有三个改变this的方法
    // 箭头函数没有arguments
    
    // 声明
    var init = () => { ... }
    
    // 作为参数
    function init(cb){
       cb(111)
    }
    // 旧版
    init(function(num){ console.log(num )})
    // 箭头函数
    init((num)=>{ console.log(num })
    

    箭头函数是用来留住this的,具体查看下一篇

    数组的拓展
    新es给给数组增加了一个叫Iterator的东西,这个查看《遍历总结》
    新增了大量的遍历方式,这个查看《遍历总结》
    还有拓展运算符代替function的apply方法(apply是什么查看《上下文和作用域》)

    // ES5取数组的最大值
    Math.max.apply(null, [14, 3, 77])
    // ES6取数组的最大值
    Math.max(...[14, 3, 77])
    
    // ES5合并数组
    arr1.concat(arr2, arr3);
    // [ 'a', 'b', 'c', 'd', 'e' ]
    // ES6合并数组
    [...arr1, ...arr2, ...arr3]
    
    // ES5把伪数组转成数组
    Array.prototype.slice.apply(null,ArrayLike)
    // ES6把伪数组转成数组
    [...ArrayLike]
    // 或者新api
    Array.from(ArrayLike)
    
    // ES5查看是否含有,返回第一个出现的位置,没有是-1
    arr.indexOf("xx")
    // ES6查看是否含有,返回true/false
    arr.include("xx")
    

    对象的扩展

    // 最后一个key-value可以加逗号了
    var obj = {
       name: "name",
       age: 18,  //以前这里结束加逗号是不行的
    }
    
    // key-value同名可以省略
    // 比如要ajax传个参数
    var name = "name",age = 18;
    ajax({
       // 以前
       // data:{ name: name, age:  gae }
       // 现在可以
       data:{name,age}
    })
    
    // 对象的value是function的写法优化
    // 老写法
    var obj = {
       say: function(){ ... }
    }
    // 新写法
    var obj = {
       say(){ ... }
    }
    
    // 对象的遍历,查看《遍历的总结》
    // 增加可Obj.vaules() 和 Object.entries()
    
    // 对象的合并assign,这个api是浅拷贝
    const target = { a: 1 };
    const source1 = { b: 2 };
    const source2 = { c: 3 };
    Object.assign(target, source1, source2);
    target // {a:1, b:2, c:3}
    // 也可以
    let target = {...target, ...source1}
    

    新类型Set【集合】
    Set跟数组差不多,同样是一个畸形的对象
    他会自动去重,但只能去重基础数据类型

    // 需要通过new去创建,参数是一个数组或者伪数组
    let set = new Set([undefined,undefined,NaN,NaN,"",""]); //  set{"undefined",NaN,""}
    
    // set的长度属性
    set.size  //3
    
    // 添加某个值,返回set本身,所以可以无限add()
    set.add(value)
    // 删除某个值,返回一个布尔值,表示删除是否成功
    set.delete(value)
    // 返回一个布尔值,表示该值是否为Set的成员
    set.has(value)
    // 清除所有成员,没有返回值
    set.clear()
    
    // Set没有办法取值,只能转数组再取值
    [...set]
    // 或者
    Array.from(set)
    
    // Set的遍历,set.keys(),set.values(),set.entries()
    // 具体查看《遍历总结》
    
    // 还有一个WeakSet,不重要
    // 他跟Set一样,只是他只能存对象,并且带有垃圾回收功能,面试题来着
    const ws = new WeakSet();
    

    集合的几个特性

    let a = new Set([1, 2, 3]);
    let b = new Set([4, 3, 2]);
    
    // 并集
    let union = new Set([...a, ...b]);
    // Set {1, 2, 3, 4}
    
    // 交集
    let intersect = new Set([...a].filter(x => b.has(x)));//ES6
    var intersect = new Set([...a].filter(function(x){
        return b.has(x);
    }))
    // set {2, 3}
    
    // 差集
    let difference = new Set([...a].filter(x => !b.has(x)));
    // Set {1}
    

    新类型Map【字典】
    Map 结构提供了value-value的对应,相比于Object,他的key可以是任一类型

    // 通过new创建,参数是一个数组,数组里的值必须都是两个长度的数组
    const map = new Map([
      ['name', '张三'],
      ['title', 'Author']
    ]);
    
    // map的长度属性
    map.size // 2
    
    
    // 添加某个值,返回set本身,所以可以无限add()
    map.set(key, value)
    // 返回一个布尔值,表示该值是否为Set的成员
    set.has(key)
    // 
    map.get(key) 
    // 删除某个值,返回一个布尔值,表示删除是否成功
    map.delete(key)
    // 清除所有成员,没有返回值
    map.clear()
    
    // Map的遍历,map.keys(),map.values(),map.entries()
    // 具体查看《遍历总结》
    
    // Map转数组,其实map挺好用的,没必要转,除非是要传给后端
    [...map]
    
    
    // 还有一个WeakMap,不重要
    // 只接受对象作为键名(null除外),不接受其他类型的值作为键名
    const wm = new WeakMap();
    

    其实Set和Map也非常的稀有,因为数组和对象就已经很好用了,而且还要去兼容,而且还要去转格式转来转去的

    Reflect
    Reflect是ES6为了操作对象而新增的API,配合proxy对数据进行操作简直完美

    Reflect.get(target, name, receiver)
    Reflect.set(target,name,value,receiver)
    Reflect.apply(target,thisArg,args)
    Reflect.construct(target,args[, newTarget])
    Reflect.defineProperty(target,name,desc)
    Reflect.deleteProperty(target,name)
    Reflect.has(target,name)
    Reflect.ownKeys(target)
    Reflect.preventExtensions(target)
    Reflect.isExtensible(target)
    Reflect.getOwnPropertyDescriptor(target, name)
    Reflect.getPrototypeOf(target)
    Reflect.setPrototypeOf(target, prototype)
    

    Proxy观察者
    这个一般来说是用不到的,是属于架构层面的api了,Vue3.0就是以这个为基础架构的,跟Object.defineProperty一样,这个放在《vue的原理设计》说

    // 贴个基础代码
    var obj = new Proxy({}, {
      get: function (target, key, receiver) {
        console.log(`getting ${key}!`);
        return Reflect.get(target, key, receiver);
      },
      set: function (target, key, value, receiver) {
        console.log(`setting ${key}!`);
        return Reflect.set(target, key, value, receiver);
      }
    });
    

    Promise
    查看《promise篇》
    Promise里装的都应该是异步函数,如果是同步的反而是产生BUG

    // 贴个基础代码
    new Promise(function(resolve, reject) {
      if (/* 异步操作成功 */){
        resolve(value);
      } else {
        reject(error);
      }
    }).then((value)=>{ ... },(error)=>{ ... })
    

    Async
    查看《promise篇》
    await后面跟着的都是promise异步函数,如果是同步的反而是产生BUG

    // 贴个基础代码
    async function main() {
      try {
        const val1 = await firstStep();
        const val2 = await secondStep(val1);
        const val3 = await thirdStep(val1, val2);
        console.log('Final: ', val3);
      }
      catch (err) {
        console.error(err);
      }
    }
    

    class
    查看《class》篇
    class就是一个新型的构造函数

    // 贴个基础代码
    class A {
      constructor(name) {
         // 静态属性/方法
        this.name = name;
      }
      // 相当于原型方法,class不支持原型属性
      print() {
        console.log(this.name);
      }
      // 带有static是私有方法/属性,通过A.myMethod()执行
      static myMethod() {
        console.log('static');
      }
    }
    
    class B extends A {
      constructor(name,age) {
        //继承的
        super();
        this.name = name;
        this.age= age;
      }
      m() {
        console.log(this.age);
      }
    }
    
    let b = new B("pdt",18);
    b.m() // 18
    b.print() // "pdt"
    

    module
    查看《模块化》篇
    引入js文件的新api但是不被支持,浏览器没支持连nodejs都没支持

    // 开放多个,只能全是export,不能有export default
    // fs.js
    export function A(){ ... }
    export B = { ... }
    export C = []
    export D = "D"
    
    // 引入并且解构赋值
    import { A, B, C, D } from 'fs';
    
    // 只能出现一个export default,并且不能有其他export
    // default就不需要名字了
    // fs.js
    export default function(){ ... }
    // 或者对象,其他格式都行
    export default {}
    
    // 引入并且解构赋值
    import fs from 'fs';
    

    除了上面常用的
    还有Symbol,Decorator【装饰器】

    装饰器文章

    1. Method Decorator 函数装饰器
    2. Property Decorators 熟悉装饰器
    3. Class Decorator 类装饰器
    4. Parameter Decorator 参数装饰器
      将来装饰器会变成新的框架,会被制造出像Spring的框架

    说几句
    这些api升级了js的难度,生产出了大量的玩法和框架,他让前端不再是个jq打天下的菜鸡,他需要学的东西越来越多,这些api高仿自很多的语言,特别是java
    比如说拓展运算符,Iterator遍历器,Set,Map,await的原生就是一个yeild,这个也是java的,还有class,model的import,Decorator就是java的注解以及NodeJs的stream流等等

  • 相关阅读:
    父组件和子组件之间的生命周期执行顺序
    Vue生命周期四个阶段
    Vue watch监听
    Vue computed计算属性 理解
    Vue中v-if 与 v-show的区别
    虚拟DOM
    MVC与MVVM原理
    单例模式 回流与重绘
    判断某个对象属于哪种数据类型
    原生JS的兼容性问题
  • 原文地址:https://www.cnblogs.com/pengdt/p/12037960.html
Copyright © 2020-2023  润新知