Frontend Development 11 min read

Understanding the Decorator Pattern and AOP in JavaScript

This article explains the decorator pattern and how Aspect‑Oriented Programming (AOP) can be used in JavaScript to dynamically extend object behavior, provides classic and Vue‑based code examples, discusses advantages and drawbacks, and outlines practical scenarios for applying decorators in front‑end development.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Understanding the Decorator Pattern and AOP in JavaScript

Definition of the Decorator Pattern

In traditional object‑oriented languages, inheritance is often used to add functionality, but it creates strong coupling between super‑classes and sub‑classes.

The decorator pattern allows dynamic addition of functionality without altering the existing object structure.

Traditional JavaScript Decorator Example

var plane = {
    fire: function () {
        console.log("普通子弹");
    },
};

var missleDecorator = function () {
    console.log("发射导弹");
};

var atomDecorator = function () {
    console.log("发射原子弹");
};

var fire1 = plane.fire;
plane.fire = function () {
    fire1();
    missleDecorator();
};

var fire2 = plane.fire;
plane.fire = function () {
    fire2();
    atomDecorator();
};

plane.fire();
/**
普通子弹
发射导弹
发射原子弹
*/

Decorator Functions (AOP)

In JavaScript, functions are objects; modifying a function directly violates the Open‑Closed Principle.

AOP can be used to add behavior before or after the original function without changing its core logic.

function a() {
    console.log(1);
}
// rewrite
function a() {
    console.log(1);
    // new feature
    console.log(2);
}

Implementation of Function.prototype.before and Function.prototype.after methods:

Function.prototype.before = function (beforeFn) {
    var _self = this;
    return function () {
        beforeFn.apply(this, arguments);
        return _self.apply(this, arguments);
    };
};

Function.prototype.after = function (afterFn) {
    var _self = this;
    return function () {
        var ret = _self.apply(this, arguments);
        afterFn.apply(this, arguments);
        return ret;
    };
};

AOP Applications

1. Log Reporting

Using AOP to attach a logging function to a button handler without modifying the original handler.

const { reactive, ref, createApp } = Vue;
const app = createApp({
    setup() {
        const message = ref("未点击");
        const count = ref(0);
        Function.prototype.before = /* same as above */;
        Function.prototype.after = /* same as above */;
        function handler() {
            message.value = `已点击${++count.value}`;
        }
        handler = handler.after(log);
        function log() {
            message.value += "-----> log reported";
            console.log("log report");
        }
        return { message, handler };
    }
});
app.mount("#app");

2. Dynamic Parameters

Injecting a token into API request parameters using AOP before the original AJAX call.

ajax = ajax.before(function (type, url, params) {
    params.token = getToken();
});

3. Form Validation

Applying validation logic before form submission without mixing validation code with business logic.

function valid() {
    if (!data.name || !data.pass) {
        alert("用户名或密码不能为空");
        return false;
    }
}
function formSubmit() {
    console.log("data -->", data);
    data.message = `${data.name} ------- ${data.pass}`;
}
formSubmit = formSubmit.before(valid);

Advantages of the Decorator Pattern

Strong extensibility – new features can be added at runtime without modifying existing code.

Adheres to the Open‑Closed Principle.

Separation of concerns – each decorator handles a single additional responsibility.

Disadvantages of the Decorator Pattern

Increases system complexity due to additional classes and layers.

Potential performance overhead from multiple wrapper objects.

Applicable Scenarios

When you need to dynamically extend object functionality at runtime.

When you want to keep existing code stable while adding new features.

When you aim to separate concerns by isolating additional behaviors.

When multiple independent features need to be combined flexibly.

As an alternative to creating numerous subclasses in inheritance hierarchies.

Tip: The article references 曾探's "JavaScript Design Patterns and Development Practice"; this is a personal learning summary.

design patternsAOPVue.jsCode ExampleDecorator Pattern
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.