最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 浅谈ECMAScript6

    正文概述 掘金(ws_qy)   2021-05-11   477

    1.Proxy

    Proxy 可以理解成,在目标对象之前架设一层"拦截",外界对该对象访问的时候

    都必须先通过这一层拦截,相当于提供了一种机制,可以对外界的访问进行过滤和改写

    var proxy = new Proxy(target, handler);
    

    Proxy对象的所有用法,都是上面这种形式,不同的只是 handler 参数的写法。其中, new Proxy() 表示

    生成一个Proxy实例,target参数表示所要拦截的目标对象, handler 参数也是一个对象,用来定制拦截行为。

    • get方法拦截读取,里面有两个参数,传入的对象与属性
    • set方法可以设置属性值,但是不会改变原有对象,拦截对象属性的赋值操作
    • has方法可以拦截判断该对象中是否有该属性
    • 拦截delete操作

    拦截对象自身属性的读取操作

    2.Reflect

    程序在运行的时候去获取对象内部的结构就叫做反射

    1.将原先Object对象上定义的一些方法,放入Reflect对象(代码重构)  

    浅谈ECMAScript6    // Reflect.defineProperty

    2.修改了某些Object方法的返回结果

    浅谈ECMAScript6 3.让Object操作变成函数行为

    •    name in obj/delete obj.name 命令式
    •    Reflect.has(obj.name)/Reflect.deleteProperty(obj,name)

    浅谈ECMAScript6

     4.Reflect对象的方法和Proxy对象方法对应

       //可以让Proxy方便的调用对应的Reflect方法

    5.修改指定函数的this指向

    浅谈ECMAScript6

    浅谈ECMAScript6

    求数组的最大值最小值

    浅谈ECMAScript6

    浅谈ECMAScript6

    浅谈ECMAScript6 3.观察者模式

    在监听对象属性改变的同时,执行指定其他的业务操作
    
     //先定义一个容器,存放需要执行的业务操作
    
    ​    let box = new Set()
    
    ​    //定义一个函数将所有的业务操作都放进去
    
    ​    let actions = fn => {
    
    ​      box.add(fn)
    
    ​    }
    
    ​    // 定义两个业务
    
    ​    let fn1 = () => {
    
    ​      console.log("业务一")
    
    ​    }
    
    ​    actions(fn1)//传入参数,目的是将业务放入容器中
    
    ​    let fn2 = () => {
    
    ​      console.log("业务二")
    
    ​    }
    
    ​    actions(fn2)//传入参数,目的是将业务放入容器中
    
    
    
    ​    //创建一个函数用于生成一个代理对象
    
    ​    let createproxy = target => new Proxy(target, {
    
    ​      set(target, key, value) {
    
    ​        Reflect.set(target, key, value)//设置值
    
    ​        //执行其他业务操作
    
    ​        box.forEach(fn => {
    
    ​          fn()//遍历放在容器中的业务操作,并执行
    
    ​        })
    
    ​      }
    
    ​    })
    
    ​    //定义一个实例对象
    
    ​    let obj = {
    
    ​      name: "wangsu",
    
    ​      age: 23,
    
    ​      grade: 90,
    
    ​      __job__: "IT"
    
    ​    }
    
    ​    //修改属性,调用函数执行
    
    ​    let proxy = createproxy(obj)
    
    ​    proxy.name = "kobe"
    

    4.promise

    4.1.promise的定义(面试重点)

    浅谈ECMAScript6

    Promise是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区

    最早提出和实现,ES6将其写进了语言标准,统一了用法,原生提供了 Promise 对象。

    所谓 Promise ,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结

    果。从语法上说,Promise是一个对象,从它可以获取异步操作的消息。Promise提供统一的API,各种异步操

    作都可以用同样的方法进行处理。

        ## 4.2 Promise两个特点
    

    1. 对象的状态不受外界影响。 Promise 对象代表一个异步操作,有三种状态: Pending (进行 中)、 Resolved (已完成,又称Fulfilled)和 Rejected (已失败)。只有异步操作的结果,可以决定当

    前是哪一种状态,任何其他操作都无法改变这个状态。这也是 Promise 这个名字的由来,它的英语意思就

    是“承诺”,表示其他手段无法改变。

    2. 一旦状态改变,就不会再变,任何时候都可以得到这个结果.

     Promise 对象的状态改变,只有两种可能:从 Pending 变为 Resolved 和从 Pending 变
     为 Rejected 。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。
     就算改变已经发生了,你再对 Promise 对象添加回调函数,也会立即得到这个结果。这与事
     件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。
     了 Promise 对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调
     函数。此外, Promise 对象提供统一的接口,使得控制异步操作更加容易。
    

    3. Promise 也有一些缺点。

    - 首先,无法取消 Promise ,一旦新建它就会立即执行,无法中途取消。
    - 其次,如果不设置回调函数, Promise 内部抛出的错误,不会反应到外部。
    - 第三,当处于 Pending 状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
    - 如果某些事件不断地反复发生,一般来说,使用stream模式是比部署 Promise 更好的选择。
    

    4.3.promise解决文件读取顺序和回调地狱问题

    let fs = require("fs")
    //封装一个读文件的方法
    function reads(path) {
      return new Promise((resolve, reject) => {//返回一个promise
    ​    fs.readFile(path, (err, data) => {//读取文件数据
    ​      if (!err) {
    ​        resolve(data.toString())//将读取的数据用resolve返回出去
    ​      }
    ​      else {
    ​        reject(err)//发送拒绝后抛错
    ​      }
    
    ​    })
    
      })
    
    }
    
    reads("../data/a.txt")
      .then((data) => {//这里函数中的data便是resolve 中返回出来已经读取的数据
    ​    console.log(data)
    ​    return reads("../data/b.txt")
    ​    //这里返回下一个需要读取的文件,在调用一下读取函数,这个函数的返回值是一个Promise
    
      },
    ​    (err) => {
    ​      throw err
    ​    } ).then((data) => {
    ​    //由于封装的reads方法返回的是一个promise对象,因此可以继续调用它的then方法
    ​    console.log(data)
    ​    return reads("../data/c.txt")
      },(err) => {
    ​      throw err
    ​    }).then((data) => {
    ​      console.log(data)
    ​      return reads("../data/d.txt")
    ​    },
    ​      (err) => {
    ​        throw err
    ​      }
    ​    ).then((data) => {
    ​      console.log(data)
    ​    },
    ​      (err) => {
    ​        throw err
    ​      }
    ​    )
    

    4.4.promise异步解决

    浅谈ECMAScript6

    由于开始的时候settimeout是一种异步处理函数,那么当程序执行时,程序不会从上到下依次
    执行,遇到异步处理时不会等待,此时会造成settimeoutl里面的代码执行可能会在其他代码
    执行之后
    

    4.5.promise-all

    浅谈ECMAScript6

    4.6.promise-race

    加载请求速度最快的那个请求

    浅谈ECMAScript6

    4.7.模拟promise图片加载

    //创建一个图片加载函数
    ​    function loadImage(url,resolve,reject) {
    ​      let img = new Image()
    ​      img.src = url
    ​      img.onload = function () {
    ​        console.log("图片加载成功")
    ​        resolve({width:img.width,height:img.height})//在函数中传入参数(图片
    的高度宽度)
    
    ​      }
    
    ​      img.onerror = function () {
    ​        console.log("图片加载失败")
    ​        reject()
    ​      }
    ​    }
    
    ​    let url="https://ss0.bdstatic.com/94oJfD_bAAcT8t7mm9GUKT-xh_/timg?
    image&quality=100&size=b4000_4000&sec=1594954864&di=c86ca29e92ae5ba6ef0400ba
    dc17a69a&src=http://a3.att.hudong.com/14/75/01300000164186121366756803686.jpg"
    
    ​    
       //创建两个函数,分别是图片加载完成和图片加载失败
    ​    function resolve(data) {
    ​      console.log("图片加载完成,执行某个处理")
    ​      console.log(data)
    ​    }
    
    ​    function reject() {
    
    ​      console.log("图片加载失败,执行某个处理")
    ​    }
    ​    loadImage(url,resolve,reject)
    

    5.defineproperty数据劫持

    // 这是将要被劫持的对象
    const data = {
      name: '',
    };
    
    function say(name) {
      if (name === '古天乐') {
        console.log('给大家推荐一款超好玩的游戏');
      } else if (name === '渣渣辉') {
        console.log('戏我演过很多,可游戏我只玩贪玩懒月');
      } else {
        console.log('来做我的兄弟');
      }
    }
    
    // 遍历对象,对其属性值进行劫持
    Object.keys(data).forEach(function(key) {
      Object.defineProperty(data, key, {
        enumerable: true,
        configurable: true,
        get: function() {
          console.log('get');
        },
        set: function(newVal) {
          // 当属性值发生变化时我们可以进行额外操作
          console.log(`大家好,我系${newVal}`);
          say(newVal);
        },
      });
    });
    
    data.name = '渣渣辉';
    //大家好,我系渣渣辉
    //戏我演过很多,可游戏我只玩贪玩懒月
    

    6.字符串匹配方法

    浅谈ECMAScript6

    浅谈ECMAScript6

    7.symbol

    7.1.基本意义

    浅谈ECMAScript6

    7.2.symbol作为属性调用

    浅谈ECMAScript6

    8.Set与Map

    8.1.set

    8.1.1.常用方法

    浅谈ECMAScript6

    8.1.2.数组去重

    浅谈ECMAScript6

    浅谈ECMAScript6

    8.1.3.并集,差集,交集

    浅谈ECMAScript6

    8.2.WeakSet

    8.2.1.与set的区别

    eakSet 结构与 Set 类似,也是不重复的值的集合。但是,它与 Set 有两个区别。

    首先,WeakSet 的成员只能是对象,而不能是其他类型的值。

    const ws = new WeakSet();
    ws.add(1)
    // TypeError: Invalid value used in weak set
    ws.add(Symbol())
    // TypeError: invalid value used in weak set
    

    上面代码试图向 WeakSet 添加一个数值和Symbol值,结果报错,因为 WeakSet 只能放置对象。

    8.2.2.基本概念(面试问到)

    其次,WeakSet 中的对象都是弱引用,即垃圾回收机制不考虑 WeakSet 对该对象的引用,也就是说,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内
    存,不考虑该对象还存在于 WeakSet 之中。
    
    这是因为垃圾回收机制依赖引用计数,如果一个值的引用次数不为,垃圾回收机制就不会释放
    这块内存。结束使用该值之后,有时会忘记取消引用,导致内存无法释放,进而可能会引发内
    存泄漏。WeakSet 里面的引用,都不计入垃圾回收机制,所以就不存在这个问题。因此,
    WeakSet 适合临时存放一组对象,以及存放跟对象绑定的信息。只要这些对象在外部消失,它
    在 WeakSet 里面的引用就会自动消失。
    
    由于上面这个特点,WeakSet 的成员是不适合引用的,因为它会随时消失。另外,由于
    WeakSet 内部有多少个成员,取决于垃圾回收机制有没有运行,运行前后很可能成员个数是不
    一样的,而垃圾回收机制何时运行是不可预测的,因此 ES6 规定 WeakSet 不可遍历
    

    8.3.map

    JavaScript 的对象(Object),本质上是键值对的集合(Hash 结构),但是传统上只能用字符串当作键。这给它的使用带来了很大的限制。

    const data = {};
    const element = document.getElementById('myDiv');
    
    data[element] = 'metadata';
    data['[object HTMLDivElement]'] // "metadata"
    

    上面代码原意是将一个 DOM 节点作为对象data的键,但是由于对象只接受字符串作为键名,所以element被自动转为字符串[object HTMLDivElement]。

    为了解决这个问题,ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。如果你需要“键值对”的数据结构,Map 比 Object 更合适。

    上面代码在新建 Map 实例时,就指定了两个键name和title

    size属性返回 Map 结构的成员总数。

    const map = new Map();
    map.set('foo', true);
    map.set('bar', false);
    
    map.size // 2
    

    set方法设置键名key对应的键值为value,然后返回整个 Map 结构。如果key已经有值,则键值会被更新,否则就新生成该键。

    const m = new Map();
    m.set('edition', 6)        // 键是字符串
    m.set(262, 'standard')     // 键是数值
    m.set(undefined, 'nah')    // 键是 undefined
    

    set方法返回的是当前的Map对象,因此可以采用链式写法。

    let map = new Map()
      .set(1, 'a')
      .set(2, 'b')
      .set(3, 'c');
    

    get方法读取key对应的键值,如果找不到key,返回undefined。

    const m = new Map();
    const hello = function() {console.log('hello');};
    m.set(hello, 'Hello ES6!') // 键是函数
    m.get(hello)  // Hello ES6!
    

    has方法返回一个布尔值,表示某个键是否在当前 Map 对象之中。

    const m = new Map();
    m.set('edition', 6);
    m.set(262, 'standard');
    m.set(undefined, 'nah');
    m.has('edition')     // true
    m.has('years')       // false
    m.has(262)           // true
    m.has(undefined)     // true
    

    delete方法删除某个键,返回true。如果删除失败,返回false。

    const m = new Map();
    m.set(undefined, 'nah');
    m.has(undefined)     // true
    m.delete(undefined)
    m.has(undefined)       // false
    

    clear方法清除所有成员,没有返回值。

    let map = new Map();
    map.set('foo', true);
    map.set('bar', false);
    map.size // 2
    map.clear()
    map.size // 0
    

    9.itertor遍历器

    9.1.基本概念

    浅谈ECMAScript6

    浅谈ECMAScript6

      let target = [1, 2, 34, 6, 8, 45, 31, 2]
    
    ​    function myinter(arr) {
    
    ​      let index = 0
    
    ​      return {
    
    ​        next() {
    
    return index < arr.length ? { value: arr[index++], done: false } : { value: undefined, done: true }
    
    ​     //设置index,使得每次调用next方法时,index加一,对应数组的索引值
    
    }
    
    ​      }
    
    ​    }
    
    ​    let it = myinter(target)//函数调用
    
    ​    // console.log(it.next())
    
    ​    // console.log(it.next())
    
    ​    // console.log(it.next())
    
    ​    // console.log(it.next())
    
    ​    for (let i = 0; i <= target.length; i++) {
    
    ​      console.log(it.next())//调用封装后的next方法
    
    ​    }
    

    9.2.接口部署

    对象无法使用for of遍历,因为内部没有遍历器

    所有能够用for of遍历的对象,需要在它的Sysbol.itertor属性上部署一个itretor接口

    浅谈ECMAScript6

    • 部署好接口后,对象便可以使用for of遍历

    浅谈ECMAScript6

    10.Generator函数

    10.1.两个特征

    异步解决的方案,是一个状态机,封装了多个状态

    • 1.function后有个*
    • 2.函数体内使用yield定义不同的内部状态

    10.2.初步使用

     function* fn() {
    
    ​      yield "hello";//第一个状态
    
    ​      yield "world";//第二个状态
    
    ​      return "endconing";//第三个状态
    
    ​    }
    
    ​    //调用函数
    
      let fn1 = fn()//函数不会立即执行,返回一个遍历器对象
    ​    //第一次调用,Generator函数开始执行,直到遇到第一个 yield 语句为止。 next 
    //方法返回一个对象,
    
    ​    //它 的 value 属性就是当前 yield 语句的值hello, done 属性的值false,表示
    //遍历还没有结束
    
    ​    let a1= fn1.next()
    ​    console.log(a1
    ​    // 第二次调用,Generator函数从上次 yield 语句停下的地方,一直执行到下一个 
    //yield 语句。 next 方法
    
    ​    // 返回的对象的 value 属性就是当前 yield 语句的值world, done 属性的值
    //false,表示遍历还没有结束。
    
    ​    let a2= fn1.next()
    
    ​    console.log( a2)
    
    
    
    ​    // 第三次调用,Generator函数从上次 yield 语句停下的地方,一直执行到 return 语句
    
    ​    // (如果没有return语句,就执行到函数结束)。next 方法返回的对象的value属性,
    
    ​    // 就是紧跟在 return语句后面的表达式的值(如果没有 return 语句,则 value 属
    //性的值为undefined),
    
    ​    // done 属性的值true,表示遍历已经结束
    
    ​    let a3=fn1.next()
    
    ​    console.log( a3)
    
    ​    // 第四次调用,此时Generator函数已经运行完毕, next 方法返回对象的 value 属
    //性为 undefined,
    
    ​    // done 属性为true。以后再调用 next 方法,返回的都是这个值。
    
    ​    let a4=fn1.next()
    
    ​    console.log( a4)
    

    浅谈ECMAScript6

    10.3.与itertor接口的关系

    浅谈ECMAScript6

    相似之处在于,都能返回紧跟在语句后面的那个表达式的值。区别在于每次遇到yield,函数暂停执行,下一次再从该位置继续向后执行,而return语句不具备位置记忆的功能。一个函数里面,只能执行一次(或者说一个)return语句,但是可以执行多次(或者说多个)yield表达式。

    浅谈ECMAScript6

    11.数组解构赋值惰性求值

    浅谈ECMAScript6

    12.class类

    12.1.class基本语法

    浅谈ECMAScript6

    12.2.静态成员

    浅谈ECMAScript6

    浅谈ECMAScript6

    12.3.类继承

    12.3.1.基本语法

    Class 可以通过关键字实现继承,这比 ES5 的通过修改原型链实现继承,要清晰和方便很多。

    浅谈ECMAScript6 上面代码定义了一个类,该类通过关键字,继承了类的所有属性和方法。但是由于没有部署任何代码,所以这两个类完全一样,等于复制了一个类。下面,我们在内部加上代码。

    浅谈ECMAScript6 上面代码中,方法和方法之中,都出现了关键字,它在这里表示父类的构造函数,用来新建父类的对象。

    子类必须在方法中调用方法,否则新建实例时会报错。这是因为子类自己的对象,必须先通过
    父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,加上子
    类自己的实例属性和方法。如果不调用方法,子类就得不到对象。
    

    12.3.2super 关键字

    super 关键字需要写下子类this之前,相当于借用了父类的构造函数

    图下:子类需要继承父类的tostring方法,需要使用super.tostring的方式

    浅谈ECMAScript6

    13.新定义的的Object方法

    1.Object.setPrototypeOf

    浅谈ECMAScript6

    2.Object.keys

    浅谈ECMAScript6

    3.Object.values

    浅谈ECMAScript6

    4.Object.entries

    浅谈ECMAScript6

    5.getOwnPropertyDescriptor

    浅谈ECMAScript6

    6.Object.assign()

    Object.assign()方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。

    const target = { a: 1 };
    const source1 = { b: 2 };
    const source2 = { c: 3 };
    Object.assign(target, source1, source2);
    target // {a:1, b:2, c:3}
    

    注意,如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。

    const target = { a: 1, b: 1 };
    const source1 = { b: 2, c: 2 };
    const source2 = { c: 3 };
    Object.assign(target, source1, source2);
    target // {a:1, b:2, c:3}
    
    • 如果只有一个参数,Object.assign()会直接返回该参数。
    const obj = {a: 1};
    Object.assign(obj) === obj // true
    

    14.函数的rest参数与扩展运算符

    14.1.rest参数

    浅谈ECMAScript6

    14.2.扩展运算符

    15.数组中增加的一些方法

    15.1.find,findindex,filter的比较

    浅谈ECMAScript6

    15.2.value,key,entries的比较

    浅谈ECMAScript6

    16.函数参数的解构赋值

    浅谈ECMAScript6

    17.箭头函数

    浅谈ECMAScript6 上面代码之中,只有一个,就是函数的,所以都输出同样的结果。因为所有的内层函数都是箭头函数,都没有自己的,它们的其实都是最外层函数的。

    18.链判断运算符

    浅谈ECMAScript6

    浅谈ECMAScript6

    浅谈ECMAScript6

    19.async 函数

        //1.使用then方法调用
    ​    //2.使用await
    ​    //只能在async函数中使用,await之后只能是一个promise对象
    

    19.2具体使用

    //request.js封装请求
    let baseUrl="http://192.168.24.36:3000/"
    
    function http(url){
      return $.ajax({
    ​    url:baseUrl+url,
    ​    type:"get"
      })
    
    }
    
    //index.html页面中发送请求
    let url="top/playList?cat=华语"
    ​    async function getdata(){
    ​      let cat=await http(url)
    ​      let id=cat.playlists[0].id
    ​      let detail=await http(`playlist/detail?id=${id}`)
    ​      let songId=detail.playlist.tracks[0].id
    ​      let songurl=await http(`song/url?id=${songId}`)
    ​      console.log(songurl)
    ​    }
    
    ​    getdata()
    

    20总结

    21.参考文献

    • ECMAScript6 (原著:阮一峰)
    • 深入理解ES6

    起源地下载网 » 浅谈ECMAScript6

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元