SoFunction
Updated on 2025-04-07

Detailed explanation of oriented oriented programming in Javascript

Aspect-oriented programming (AOP) is a programming paradigm. Students who do back-end Java web, especially those who have used Spring, must be very familiar with it. AOP is one of the important concepts in the Spring framework. But in Javascript, AOP is a technical point that is often overlooked.

Scene

Suppose you have an awesome calendar pop-up window now. One day, the boss asks you to count the number of clicks on a button in this pop-up window every day, so you buried the point in the pop-up window;

A week later, the boss said that the user feedback on this pop-up window was so slow and there were all kinds of lags. You want to see the average execution time of a certain function, so you add performance statistics code to the pop-up window.

Over time, you will find that your business logic contains a lot of business-independent things, even some functions that you have already encapsulated.
Then AOP exists to solve this kind of problem.

Separation of concerns

Separating business code and data statistics code (non-business code), no matter what language, is one of the classic applications of AOP. Separating cross-cutting concerns from core concerns is the core concept of AOP.
Among the common front-end requirements, there are some businesses that can be separated from their core concerns using AOP

  1. Log log
  2. Buried points, data reporting
  3. Performance analysis, statistical function execution time
  4. Dynamically add parameters to ajax request and dynamically change function parameters
  5. Separate form requests and verifications
  6. Anti-shake and throttling

Decorator

When it comes to AOP, we need to talk about decorator mode. AOP is often confused with decorator mode.

Before ES6, decorator mode is used, usually by doing predecoration and post-decoration (see "Javascript Design Patterns and Development Practice").

The Decorator introduced by Javascript is very syntactically similar to Java's annotations, but has no semantic relationship. The Decorator proposal provides the ability to decorate Javascript classes and methods in classes. (Although it's just function syntax sugar that runs at compile time)

Buried data reporting

Because there are a large number of Class-based Components in actual development using React, I use React as an example here.
For example, there is a button on the page now. Clicking on this button will bring up a pop-up window. At the same time, data reporting is required to count how many users clicked on this login button.

import React, { Component } from 'react';
import send from './send';

class Dialog extends Component {

  constructor(props) {
    super(props);
  }

  @send
  showDialog(content) {
    // do things
  }

  render() {
    return (
      <button onClick={() => ('show dialog')}>showDialog</button>
    )
  }
}

export default Dialog;

The above code references the @send decorator, which will modify the prototype method on this Class. The following is the implementation of the @send decorator

export default function send(target, name, descriptor) {
  let oldValue = ;

   = function () {
    (`before calling ${name} with`, arguments);
    return (this, arguments);
  };

  return descriptor;
}

Before executing showDialog after the button is clicked, we can perform the sectional operation we want. We can encapsulate the relevant code of the buried point and data reporting in this decorator to implement AOP.

Front and rear decoration

The send decorator above is actually a predecorator. We can encapsulate it so that it can pre-execute any function.

function before(beforeFn = function () { }) {
  return function (target, name, descriptor) {
    let oldValue = ;

     = function () {
      (this, arguments);
      return (this, arguments);
    };

    return descriptor;
  }
}

This way we can use the @before decorator to cut into arbitrary non-business code before a prototype method.

function beforeLog() {
  (`before calling ${name} with`, arguments);
}
class Dialog {
  ...
  @before(beforeLog)
  showDialog(content) {
    // do things
  }
  ...
}

Similar to @before decorator, you can implement a @after post decorator, except that the execution order of the functions is different.

function after(afterFn = function () { }) {
  return function (target, name, descriptor) {
    let oldValue = ;

     = function () {
      let ret = (this, arguments);
      (this, arguments);
      return ret;
    };

    return descriptor;
  }
}

Performance Analysis

Sometimes we want to count the execution time of a piece of code on the user side, but we don’t want to embed the code into the business code. We can also use decorators to make AOP.

function measure(target, name, descriptor) {
  let oldValue = ;

   = function () {
    let ret = (this, arguments);
    ("startWork");
    (this, arguments);
    ("endWork");
    ("work", "startWork", "endWork");
    performance
     .getEntries()
     .map(entry => (entry, null, 2))
     .forEach(json => (json));
    return ret;
  };

  return descriptor;
}

Just add @measure to the class method that wants to count the execution time, so that the code for performance statistics will not invade the business code.

class Dialog {
  ...
  @measure
  showDialog(content) {
    // do things
  }
  ...
}

summary

The focus of section-oriented programming is to separate the core focus surface from the cross-section focus surface. The front-end can use AOP to elegantly organize data reporting, performance analysis, statistical function execution time, dynamic change of function parameters, plug-in form verification and other codes.

The above is the detailed explanation and integration of Javascript-oriented tangible programming introduced by the editor. I hope it will be helpful to everyone. If you have any questions, please leave me a message and the editor will reply to everyone in time. Thank you very much for your support for my website!