专栏首页FinGet前端之路JavaScript设计模式之装饰器模式

JavaScript设计模式之装饰器模式

装饰器模式

为对象添加新功能;不改变其原有的结构和功能。

手机壳就是装饰器,没有它手机也能正常使用,原有的功能不变,手机壳可以减轻手机滑落的损耗。

代码示例

class Circle {
  draw() {
    console.log('画一个圆形')
  }
}
class Decorator {
  constructor(circle) {
    this.circle = circle
  }
  draw() {
    this.circle.draw()
    this.setRedBorder(circle)
  }
  setRedBorder(circle) {
    console.log('设置红色边框')
  }
}

// 测试
let circle = new Circle()
circle.draw()

let decorator = new Decorator(cicle)
decorator.draw()

ES7装饰器

// 简单的装饰器
@testDec // 装饰器
class Demo {}

function testDec(target){
  target.isDec = true
}
console.log(Demo.isDec) // true
// 装饰器原理
@decorator
class A {}

// 等同于
class A {}
A = decorator(A) || A; // 把A 作为参数,返回运行的结果
// 传参数
function testDec(isDec) {
  return function(target) { // 这里要 return 一个函数
    target.isDec = isDec;
  }
}
@testDec(true)
class Demo {
  // ...
}
alert(Demo.isDec) // true

装饰类

function mixins(...list) {
  return function (target) {
    Object.assign(target.prototype, ...list)
  }
}
const Foo = {
  foo() {
    console.log('foo')
  }
}
@mixins(Foo)
class MyClass{}

let myclass = new MyClass()
myclass.foo() // 'foo'

装饰方法

// 例1 只读
function readonly(target, name, descriptor){
  // descriptor对象原来的值如下
  // {
  //   value: specifiedFunction,
  //   enumerable: false, // 可枚举
  //   configurable: true, // 可配置
  //   writable: true // 可写
  // };
  descriptor.writable = false;
  return descriptor;
}

class Person {
  constructor() {
    this.first = 'A'
    this.last = 'B'
  }

  @readonly
  name() { return `${this.first} ${this.last}` }
}

var p = new Person()
console.log(p.name())
p.name = function () {} // 这里会报错,因为 name 是只读属性
// 例2 打印日志
function log(target, name, descriptor) {
  var oldValue = descriptor.value;

  descriptor.value = function() {
    // 1. 先打印日子
    console.log(`Calling ${name} with`, arguments);
    // 2. 执行原来的代码,并返回
    return oldValue.apply(this, arguments);
  };

  return descriptor;
}

class Math {
  @log
  add(a, b) {
    return a + b;
  }
}

const math = new Math();
const result = math.add(2, 4);
console.log('result', result);

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • JavaScript的预编译过程

    在全局环境中会生成一个 GO对象 (Global Object),还是按照上面的四步执行。

    FinGet
  • 原型,原型链,call/apply

    FinGet
  • JavaScript从初级往高级走系列————ES6

    在nodejs,exports 是 module.exports的引用,初始化时,它们都指向同一个{}对象。

    FinGet
  • python开发_tkinter_单选菜单_不可用菜单操作

    ============================================================

    Hongten
  • 飞行机器人BeeRotor:用视觉控制飞行

    人类保持平衡需要身体多个部位进行配合,其复杂性和精密性无法直接复制到机器人身上。因此,机器人需要采用加速计测量重力加速度,获取自身横向和纵向倾斜的角度,从而保持...

    机器人网
  • bootsrap栅格系统

    在 HTML5 的项目中,我们做了移动端的项目。它有一份非常重要的 meta,用于设置屏

    十月梦想
  • 关于 Vue 3.0,前端开发者必须知道的不仅仅是Proxy...

    前端早已经不是之前人们口中的 “抠图仔”、只是写写简单的 HTML,CSS 和脚本动画。如今的前端早已经系统化,工程化,前后端分离的开发模式带动前端工程师在开发...

    Phodal
  • 手把手的SpringBoot教程,SpringBoot创建web项目(二)

    剽悍一小兔
  • iOS苹果审核2.1解决方案审核机制

    近几个月来,在苹果审核中,只要应用中涉及,支付,定位等涉及用户隐私的功能,苹果都会部分青红皂白的打回来,这其实很可能不是APP本身的原因,只是苹果要你自查。

    Lee坚武
  • #MeToo在校园中:使用社交媒体上报告的数据大规模研究大学性侵犯(cs AI)

    最近,# MeToo趋势的出现使成千上万的人在社会媒体上分享自己的性骚扰的经验。这一病毒式的趋势,加上Twitter上大量的个人信息和内容,为我们提供了一个很好...

    DANDAN用户6837186

扫码关注云+社区

领取腾讯云代金券