所谓ES6的常用应用
- const/let
- 箭头函数
- Promise
- async await
- 解构/扩展运算符
- Object assgin
- class static
- 数组遍历api
- Reflect
Reflect.defineProperty(Vue.prototype, this.name, {value: this,writable: false,enumerable: false,configurable: false});
包装模式
装饰模式和适配器模式都是 包装模式 (Wrapper Pattern),它们都是通过封装其他对象达到设计的目的的,但是它们的形态有很大区别。
- 适配器模式我们使用的场景比较多,比如连接不同数据库的情况,你需要包装现有的模块接口,从而使之适配数据库 —— 好比你手机使用转接口来适配插座那样;

装饰类
// 装饰类@annotationclass MyClass { }function annotation(target) {target.annotated = true;}装饰方法或属性
https://github.com/mqyqingfeng/Blog/issues/109
装饰方法
装饰方法本质上还是使用 Object.defineProperty() 来实现的。
Decorators 的本质是利用了 ES5 的 Object.defineProperty 属性,这三个参数其实是和 Object.defineProperty 参数一致的
以上我们都是用于修饰类方法,我们获取值的方式为:
const method = descriptor.value;
方法装饰器有3个参数
- target
- key 方法名称
- desciptor 描述对象
@gang('The Warriors', 'Coney Island')class Group1 {constructor(){}}@gang('The Riffs', 'Gramercy Park')class Group2 {constructor(){}}@gang('Turnbull ACs', 'Gunhill')class Group3 {constructor(){}}function gang(name, location) {return function(target) {target.locName = name;target.location = location;}}console.log('location=',Group1.location)console.log('location=',Group2.location)console.log('location=',Group3.location)
应用
装饰模式经典的应用是 AOP 编程,比如“日志系统”
log注释
class Math {@logadd(a, b) {return a + b;}}function log(target, name, descriptor) {var oldValue = descriptor.value;descriptor.value = function(...args) {console.log(`Calling ${name} with`, args);return oldValue.apply(this, args);};return descriptor;}const math = new Math();// Calling add with [2, 4]math.add(2, 4);
mixin
const SingerMixin = {sing(sound) {alert(sound);}};const FlyMixin = {// All types of property descriptors are supportedget speed() {},fly() {},land() {}};@mixin(SingerMixin, FlyMixin)class Bird {singMatingCall() {this.sing('tweet tweet');}}var bird = new Bird();bird.singMatingCall();// alerts "tweet tweet"function mixin(...mixins) {return target => {if (!mixins.length) {throw new SyntaxError(`@mixin() class ${target.name} requires at least one mixin as an argument`);}for (let i = 0, l = mixins.length; i < l; i++) {const descs = Object.getOwnPropertyDescriptors(mixins[i]);const keys = Object.getOwnPropertyNames(descs);for (let j = 0, k = keys.length; j < k; j++) {const key = keys[j];if (!target.prototype.hasOwnProperty(key)) {Object.defineProperty(target.prototype, key, descs[key]);}}}};}
debonce
function _debounce(func, wait, immediate) {// return 一个function// 缓存timeout定时器IDvar timeout = null;// wrapper function// 闭包 return的fn 就被称为闭包。return function () {// 缓存thisvar context = this;var args = arguments;//连续触发fn 如果 假设一个用户一直触发这个函数,且每次触发函数的间隔小于wait,防抖的情况下只会调用一次if (timeout) clearTimeout(timeout);if (immediate) {// 是否马上调用// 第一次按下 立即调用// 然后再wait之内连续按下,timeout有了,不会立即调用,会清除timeout定时器,直到wait之后,timeout = nullvar callNow = !timeout;timeout = setTimeout(function(){timeout = null;}, wait)if (callNow) func.apply(context, args)}// 不难看出如果用户调用该函数的间隔小于wait的情况下,上一次的时间还未到就被清除了,并不会执行函数// 大于wait 函数才会被执行else {timeout = setTimeout(function(){func.apply(context, args)}, wait);}}}function debounce(wait, immediate) {return function handleDescriptor(target, key, descriptor) {const callback = descriptor.value;if (typeof callback !== 'function') {throw new SyntaxError('Only functions can be debounced');}var fn = _debounce(callback, wait, immediate)// 这样写什么意思?// return 一个descriptorreturn {...descriptor,value() {fn()}};}}
钢铁侠的例子
function decorateArmour(target, key, descriptor) {// 装饰的是init方法,必须调用initconst method = descriptor.value;let moreDef = 100;let ret;descriptor.value = (...args)=>{args[0] += moreDef;ret = method.apply(target, args);return ret;}return descriptor;}class Man{constructor(def = 2,atk = 3,hp = 3){this.init(def,atk,hp);}@decorateArmourinit(def,atk,hp){this.def = def; // 防御值this.atk = atk; // 攻击力this.hp = hp; // 血量}toString(){return `防御力:${this.def},攻击力:${this.atk},血量:${this.hp}`;}}var tony = new Man();console.log(`当前状态 ===> ${tony}`);// 输出:当前状态 ===> 防御力:102,攻击力:3,血量:3
