所谓ES6的常用应用

  • const/let
  • 箭头函数
  • Promise
  • async await
  • 解构/扩展运算符
  • Object assgin
  • class static
  • 数组遍历api
  • Reflect
  1. Reflect.defineProperty(Vue.prototype, this.name, {
  2. value: this,
  3. writable: false,
  4. enumerable: false,
  5. configurable: false
  6. });

包装模式

装饰模式和适配器模式都是 包装模式 (Wrapper Pattern),它们都是通过封装其他对象达到设计的目的的,但是它们的形态有很大区别。

  • 适配器模式我们使用的场景比较多,比如连接不同数据库的情况,你需要包装现有的模块接口,从而使之适配数据库 —— 好比你手机使用转接口来适配插座那样;

image.png

装饰类

  1. // 装饰类
  2. @annotation
  3. class MyClass { }
  4. function annotation(target) {
  5. target.annotated = true;
  6. }
  7. 装饰方法或属性

https://github.com/mqyqingfeng/Blog/issues/109

装饰方法

装饰方法本质上还是使用 Object.defineProperty() 来实现的。

Decorators 的本质是利用了 ES5 的 Object.defineProperty 属性,这三个参数其实是和 Object.defineProperty 参数一致的

以上我们都是用于修饰类方法,我们获取值的方式为:

const method = descriptor.value;

方法装饰器有3个参数

  • target
  • key 方法名称
  • desciptor 描述对象
  1. @gang('The Warriors', 'Coney Island')
  2. class Group1 {
  3. constructor(){
  4. }
  5. }
  6. @gang('The Riffs', 'Gramercy Park')
  7. class Group2 {
  8. constructor(){
  9. }
  10. }
  11. @gang('Turnbull ACs', 'Gunhill')
  12. class Group3 {
  13. constructor(){
  14. }
  15. }
  16. function gang(name, location) {
  17. return function(target) {
  18. target.locName = name;
  19. target.location = location;
  20. }
  21. }
  22. console.log('location=',Group1.location)
  23. console.log('location=',Group2.location)
  24. console.log('location=',Group3.location)

应用

装饰模式经典的应用是 AOP 编程,比如“日志系统”

log注释

  1. class Math {
  2. @log
  3. add(a, b) {
  4. return a + b;
  5. }
  6. }
  7. function log(target, name, descriptor) {
  8. var oldValue = descriptor.value;
  9. descriptor.value = function(...args) {
  10. console.log(`Calling ${name} with`, args);
  11. return oldValue.apply(this, args);
  12. };
  13. return descriptor;
  14. }
  15. const math = new Math();
  16. // Calling add with [2, 4]
  17. math.add(2, 4);

mixin

  1. const SingerMixin = {
  2. sing(sound) {
  3. alert(sound);
  4. }
  5. };
  6. const FlyMixin = {
  7. // All types of property descriptors are supported
  8. get speed() {},
  9. fly() {},
  10. land() {}
  11. };
  12. @mixin(SingerMixin, FlyMixin)
  13. class Bird {
  14. singMatingCall() {
  15. this.sing('tweet tweet');
  16. }
  17. }
  18. var bird = new Bird();
  19. bird.singMatingCall();
  20. // alerts "tweet tweet"
  21. function mixin(...mixins) {
  22. return target => {
  23. if (!mixins.length) {
  24. throw new SyntaxError(`@mixin() class ${target.name} requires at least one mixin as an argument`);
  25. }
  26. for (let i = 0, l = mixins.length; i < l; i++) {
  27. const descs = Object.getOwnPropertyDescriptors(mixins[i]);
  28. const keys = Object.getOwnPropertyNames(descs);
  29. for (let j = 0, k = keys.length; j < k; j++) {
  30. const key = keys[j];
  31. if (!target.prototype.hasOwnProperty(key)) {
  32. Object.defineProperty(target.prototype, key, descs[key]);
  33. }
  34. }
  35. }
  36. };
  37. }

debonce

  1. function _debounce(func, wait, immediate) {
  2. // return 一个function
  3. // 缓存timeout定时器ID
  4. var timeout = null;
  5. // wrapper function
  6. // 闭包 return的fn 就被称为闭包。
  7. return function () {
  8. // 缓存this
  9. var context = this;
  10. var args = arguments;
  11. //连续触发fn 如果 假设一个用户一直触发这个函数,且每次触发函数的间隔小于wait,防抖的情况下只会调用一次
  12. if (timeout) clearTimeout(timeout);
  13. if (immediate) {
  14. // 是否马上调用
  15. // 第一次按下 立即调用
  16. // 然后再wait之内连续按下,timeout有了,不会立即调用,会清除timeout定时器,直到wait之后,timeout = null
  17. var callNow = !timeout;
  18. timeout = setTimeout(function(){
  19. timeout = null;
  20. }, wait)
  21. if (callNow) func.apply(context, args)
  22. }
  23. // 不难看出如果用户调用该函数的间隔小于wait的情况下,上一次的时间还未到就被清除了,并不会执行函数
  24. // 大于wait 函数才会被执行
  25. else {
  26. timeout = setTimeout(function(){
  27. func.apply(context, args)
  28. }, wait);
  29. }
  30. }
  31. }
  32. function debounce(wait, immediate) {
  33. return function handleDescriptor(target, key, descriptor) {
  34. const callback = descriptor.value;
  35. if (typeof callback !== 'function') {
  36. throw new SyntaxError('Only functions can be debounced');
  37. }
  38. var fn = _debounce(callback, wait, immediate)
  39. // 这样写什么意思?
  40. // return 一个descriptor
  41. return {
  42. ...descriptor,
  43. value() {
  44. fn()
  45. }
  46. };
  47. }
  48. }

钢铁侠的例子

  1. function decorateArmour(target, key, descriptor) {
  2. // 装饰的是init方法,必须调用init
  3. const method = descriptor.value;
  4. let moreDef = 100;
  5. let ret;
  6. descriptor.value = (...args)=>{
  7. args[0] += moreDef;
  8. ret = method.apply(target, args);
  9. return ret;
  10. }
  11. return descriptor;
  12. }
  13. class Man{
  14. constructor(def = 2,atk = 3,hp = 3){
  15. this.init(def,atk,hp);
  16. }
  17. @decorateArmour
  18. init(def,atk,hp){
  19. this.def = def; // 防御值
  20. this.atk = atk; // 攻击力
  21. this.hp = hp; // 血量
  22. }
  23. toString(){
  24. return `防御力:${this.def},攻击力:${this.atk},血量:${this.hp}`;
  25. }
  26. }
  27. var tony = new Man();
  28. console.log(`当前状态 ===> ${tony}`);
  29. // 输出:当前状态 ===> 防御力:102,攻击力:3,血量:3

playground

jsfiddle.net/wcrowe/o5owvteL/

参考

http://taobaofed.org/blog/2015/11/16/es7-decorator/