JavaScript-裝飾器模式

来源:https://www.cnblogs.com/ygjzs/archive/2020/01/28/12239038.html
-Advertisement-
Play Games

裝飾器模式 為對象添加新功能 不改變其原有的結構和功能 傳統 UML 類圖 javascript 中的裝飾器 裝飾類 裝飾器原理 裝飾類 mixin 示例 裝飾方法 one javascript function readonly(target, name, descriptor) { // des ...


裝飾器模式

為對象添加新功能
不改變其原有的結構和功能

傳統 UML 類圖

javascript 中的裝飾器

裝飾類


@testDec
clss Demo {

}

function testDec(target) {
    target.isDec = true
}

alert(Demo.isDec)

@testDec(false)
clss Demo {

}

function testDec(isDec) {
    return function (target) {
        target.isDec = isDec
    }
}

alert(Demo.isDec)

裝飾器原理

@decorator
class A {}

//等同於

class A {}
A = decorator(a) || A;

裝飾類-mixin 示例

function mixins(...list) {
  return function(target) {
    Object.assign(target.prototype, ...list);
  };
}

const Foo = {
  foo() {
    alert("foo");
  }
};

@mixins(Foo)
class MyClass {}

let obj = new MyClass();
obj.foo(); // 'foo'

裝飾方法

one

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 是只讀屬性

two

function log(target, name, descriptor) {
  var oldValue = descriptor.value;

  descriptor.value = function() {
    console.log(`Calling ${name} with`, arguments);
    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);

core-decorators

  • 第三方開源 lib
  • 提供常用的裝飾器
  • 文檔
  • 執行npm i core-decorators --save

使用

想用什麼裝飾器,直接引入就行了

one

import { readonly } from "core-decorators";

class Person {
  @readonly
  name() {
    return "zhang";
  }
}

let p = new Person();
alert(p.name());
// p.name = function () { /*...*/ }  // 此處會報錯

two

import { deprecate } from "core-decorators";

class Person {
  @deprecate
  facepalm() {}

  @deprecate("We stopped facepalming")
  facepalmHard() {}

  @deprecate("We stopped facepalming", {
    url: "http://knowyourmeme.com/memes/facepalm"
  })
  facepalmHarder() {}
}

let person = new Person();

person.facepalm();
// DEPRECATION Person#facepalm: This function will be removed in future versions.

person.facepalmHard();
// DEPRECATION Person#facepalmHard: We stopped facepalming

person.facepalmHarder();
// DEPRECATION Person#facepalmHarder: We stopped facepalming
//
//     See http://knowyourmeme.com/memes/facepalm for more details.

設計原則驗證

  • 將現有對象和裝飾器進行分離,兩者獨立存在
  • 符合開放封閉原則

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • docker search nextcloud docker pull docker.io/nextcloud docker images mkdir /home/nextcloud chmod -R 777 nextcloud/ docker run -d --restart=always --n ...
  • spark 1. Spark的四大特性 1. 速度快 spark比mapreduce快的兩個原因 1. 基於記憶體 2. 進程與線程 2. 易用性 1. 可以用java、scala、python、R等不同的語言來快速編寫spark程式 3. 通用性 4. 相容性 1. spark程式有多種運行模式 s ...
  • Redis是用C語言編寫的開源免費的高性能的分散式記憶體資料庫,基於記憶體運行並支持持久化的NoSQL資料庫。 安裝 1)從官網http://download.redis.io/releases/下載redis壓縮包,如redis-5.0.3.tar.gz 2)上傳Linux伺服器目錄opt,解壓文件包 ...
  • html點擊圓形擴散顯示界面特效 "開場白" "效果" "用到的核心代碼" "思考" "探索" "源碼" "相容性問題" 開場白 經常看到某些app有點擊擴散的特效,有些當做擴散顯示界面,有些擴散改變主題顏色,想在網頁上實現一下,所以就有了這個。 效果 不想聽逼逼的直接去 "源碼" 用到的核心代碼 ...
  • Loader(載入器) 是 webpack 的核心之一。它用於將不同類型的文件轉換為 webpack 可識別的模塊。本文將深入探索 webpack 中的 loader,揭秘它的工作原理,以及如何開發一個 loader。 ...
  • 在我還沒開始吧學習記錄記錄在博客上時,我曾做過一張關於前端工程師的腦圖 當時我還是一個連數據結構都沒學過的小萌新,空有一腔熱血,如今我不僅學完了c語言版的數據結構(感覺收穫很大,考的還湊合), 還把JavaScript的數據結構與演算法學了一遍,再看這張圖時,已經不像當初好多都看不懂,現在下麵這張圖已 ...
  • 面向對象和麵向過程是兩種不同描述世界的方法。 面向過程:世界視為過程,世界由一個個相互關聯的小程式構建來的,是精密的。 但是構成一個系統的因素太多,要把所有可能的因素都考慮到,把所有因素的因果分析都分析清楚,再把這個過程模擬出來實在是太困難了。 面向對象:世界視為對象,世界由一個個相互獨立、相互之間 ...
  • 代理模式 使用者無權訪問目標對象 中間加代理,通過代理授權和控制 傳統 UML 類圖 JavaScript 中的代理模式 應用場景 網頁代理事件 jQuery \$.proxy es6 Proxy 明星和經紀人的關係 設計原則驗證 代理類和目標類分離,隔離開目標類和使用者 符合開放封閉原則 代理模式 ...
一周排行
    -Advertisement-
    Play Games
  • Dapr Outbox 是1.12中的功能。 本文只介紹Dapr Outbox 執行流程,Dapr Outbox基本用法請閱讀官方文檔 。本文中appID=order-processor,topic=orders 本文前提知識:熟悉Dapr狀態管理、Dapr發佈訂閱和Outbox 模式。 Outbo ...
  • 引言 在前幾章我們深度講解了單元測試和集成測試的基礎知識,這一章我們來講解一下代碼覆蓋率,代碼覆蓋率是單元測試運行的度量值,覆蓋率通常以百分比表示,用於衡量代碼被測試覆蓋的程度,幫助開發人員評估測試用例的質量和代碼的健壯性。常見的覆蓋率包括語句覆蓋率(Line Coverage)、分支覆蓋率(Bra ...
  • 前言 本文介紹瞭如何使用S7.NET庫實現對西門子PLC DB塊數據的讀寫,記錄了使用電腦模擬,模擬PLC,自至完成測試的詳細流程,並重點介紹了在這個過程中的易錯點,供參考。 用到的軟體: 1.Windows環境下鏈路層網路訪問的行業標準工具(WinPcap_4_1_3.exe)下載鏈接:http ...
  • 從依賴倒置原則(Dependency Inversion Principle, DIP)到控制反轉(Inversion of Control, IoC)再到依賴註入(Dependency Injection, DI)的演進過程,我們可以理解為一種逐步抽象和解耦的設計思想。這種思想在C#等面向對象的編 ...
  • 關於Python中的私有屬性和私有方法 Python對於類的成員沒有嚴格的訪問控制限制,這與其他面相對對象語言有區別。關於私有屬性和私有方法,有如下要點: 1、通常我們約定,兩個下劃線開頭的屬性是私有的(private)。其他為公共的(public); 2、類內部可以訪問私有屬性(方法); 3、類外 ...
  • C++ 訪問說明符 訪問說明符是 C++ 中控制類成員(屬性和方法)可訪問性的關鍵字。它們用於封裝類數據並保護其免受意外修改或濫用。 三種訪問說明符: public:允許從類外部的任何地方訪問成員。 private:僅允許在類內部訪問成員。 protected:允許在類內部及其派生類中訪問成員。 示 ...
  • 寫這個隨筆說一下C++的static_cast和dynamic_cast用在子類與父類的指針轉換時的一些事宜。首先,【static_cast,dynamic_cast】【父類指針,子類指針】,兩兩一組,共有4種組合:用 static_cast 父類轉子類、用 static_cast 子類轉父類、使用 ...
  • /******************************************************************************************************** * * * 設計雙向鏈表的介面 * * * * Copyright (c) 2023-2 ...
  • 相信接觸過spring做開發的小伙伴們一定使用過@ComponentScan註解 @ComponentScan("com.wangm.lifecycle") public class AppConfig { } @ComponentScan指定basePackage,將包下的類按照一定規則註冊成Be ...
  • 操作系統 :CentOS 7.6_x64 opensips版本: 2.4.9 python版本:2.7.5 python作為腳本語言,使用起來很方便,查了下opensips的文檔,支持使用python腳本寫邏輯代碼。今天整理下CentOS7環境下opensips2.4.9的python模塊筆記及使用 ...