Decorator装璜器

针对属性 / 办法的装璜器

// decorator 内部能够包装一个函数,函数能够带参数    function Decorator (type) {      /**       * 这里是真正的decorator       * @description: 装璜的对象的形容对象       * @target:装璜的属性所述类的原型,不是实例后的类。如果装璜的是Animal的某个属性,这个target就是Animal.prototype       * @name 装璜的属性的key       */      return function (target, name, desciptor) {        // 因为babel的缘故 通过value并不能获取值,以此能够获取实例化的时候此属性的默认值        let v = desciptor.initializer && desciptor.initializer.call(this)        // 返回一个新的形容对象,或者间接批改desciptor也能够        return {          enumerable: true, //能够遍历          configurable: true, //能够删除          get: function () {            return v          },          set: function (c) {            v = c          }        }      }    }                    // 下面的不能和业界商用的Decorator混用    function Check (type) {      return function (target, name, desciptor) {        let v = desciptor.initializer && desciptor.initializer.call(this)        // 将属性名字以及须要的类型的对应关系记录到类的原型上        if (!target.constructor._checkers_) {          // 将这个暗藏属性定义成no enumerable,遍历的时候是取不到的          Object.defineProperty(target.constructor, '_checkers_', {            value: {},            enumerable: false,            writable: true,            configurable: true          })        }        target.constructor._checkers_[name] = {          type: type        }        return desciptor      }    }    // 装璜函数的第一个参数 target 是包装属性所属的类的原型(prototype)    // 也就是把对应关系挂载到了开发定义的子类上。

vue中应用Decorator

  • ts开发肯定对vue-property-decorator不会感到生疏,这个插件提供了许多装璜器
  • 在methods外面的办法下面应用装璜器,这时候装璜器的target对应的是methods。
  • 能够在生命周期钩子函数下面应用装璜器,这时候target对应的是整个组件对象。
  import {log,confirmation} from "./test"    methods: {    @log()    name() {      console.log("获取数据");    },    @confirmation('此操作将永恒删除文件,是否持续?')    deleteFile(data){      //删除文件操作    }  },  mounted () {    this.name()  }

test.js

 import {MessageBox}from "element-ui"export function confirmation(message){    return function(target,name,descriptor){        let oldValue = descriptor.value        descriptor.value = function(...args){            MessageBox.confirm(message,'提醒').then(oldValue.bind(this,...args)).catch(()=>{})        }        return descriptor    }}export function log(){    /**     * @description:      * @param {*} target  对应methods     * @param {*} name 对应属性办法的名称     * @param {*} descriptor 对应属性办法的修饰符     * @return {*}     */          return function(target,name,descriptor){      console.log(target,name,descriptor);      // 获取实例化的时候此属性的默认值      const fn = descriptor.value      /* 重写 */      descriptor.value = function(...rest){        console.log(`调用${name}办法打印的`);        fn.call(this,...rest)      }    }  }

Iterator 迭代器

  • 目标是为不同的数据结构提供对立的数据拜访机制 次要为for of 服务的 (当for of执行的时候,循环过程中会主动调用这个对象上的迭代器办法,顺次执行迭代器对象的next办法,并把next返回后果赋值给for of的变量,从而失去具体的值
  • 迭代器对象,返回此对象的办法叫做迭代器办法 此对象有一个next办法 每次调用next办法都会返回一个后果值
  • 这个后果值是一个object 蕴含两个属性value和done
  • value示意具体的返回值 done是布尔类型的,示意汇合是否遍历实现或者后续还有可用数据,没有可用返回true, 否则返回false
  • 外部会保护一个指针 用来指向以后汇合的地位 每调用一次next办法 指针都会向后挪动一个地位(能够设想成数组的索引)

    代码实现

  getInterator(list){    var i = 0;    return {      next:function(){        var done = (i>=list.length);        var value = !done ? list[i++]:undefined        return {          done:done,          value:value        }      }    }  }      var it = this.getInterator(['a','b','c'])    console.log(it.next());// {done: false, value: 'a'}    console.log(it.next());//{done: false, value: 'b'}    console.log(it.next());//{done: false, value: 'c'}    console.log(it.next());//{done: true, value: undefined}
可迭代对象
  • Symbol.Iterator是一个表达式 返回Symbol的Iterator属性, 这是一个预约好的类型为Symbol的非凡值
  • ES6规定,只有在对象上部署了Iterator接口,具体实现为给对象增加Symbol.Iterator属性,此属性指向一个迭代器办法,这个迭代器会返回一个迭代器对象。
  • 而部署了这个属性,并且实现迭代器办法 返回的对象就是迭代器对象,此时这个对象就是可迭代的 能够被for for遍历

    实现一个可迭代对象

     getIterator(){    let iteratorObj = {      items:[100,200,300],      [Symbol.iterator]: function(){        var self = this        var i =0        return {          next:function(){            var done = (i>=self.items.length)            var value = !done?self.items[i++]:undefined            return {              done:done,              value:value            }          }        }      }    }    for(var item of iteratorObj){      console.log(item); //100 200 300    }  }    //下面的对象就是可迭代对象,能够被for of遍历    this.getIterator()
    for of 中断

    如果for of 循环提前退出,则会主动调用return办法,须要留神的是return 办法必须有返回值,且返回值必须是一个object

     var arr = [100, 200, 300]    arr[Symbol.iterator] = function () {      var self = this      var i = 0      return {        next: function () {          var done = i >= self.length          var value = !done ? self[i++] : undefined          return {            done: done,            value: value          }        },        return (){          console.log('提前退出');          return { //必须返回一个对象            done:true          }        }      }    }    for (var o of arr) {      if(o == 200){        break;      }      console.log(o) // 100   提前退出    }

    除了for of 会调用对象的Iterator, 构造赋值也会

        var str = '123'    let [a,b]=str    console.log(a,b); // 1 2    let map = new Map()      map.set('q','1')      map.set('a','2')      map.set('b','3')    let [c,d] = map    console.log(c,d); //['q', '1'] ['a', '2']

    因为一般对象不是可迭代对象。

    自定义的可迭代对象进行解构赋值

     var interatorObj = {      items: ['橙', '红', '白'],      [Symbol.iterator]: function () {        let i = 0        let self = this        return {          next: function () {            let done = i >= self.items.length            let value = !done ? self.items[i++] : undefined            return {              done: done,              value: value            }          }        }      }    }   let [a,b] = interatorObj   console.log(a,b); //橙 红