真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Javascript中怎么實現(xiàn)面向切面編程-創(chuàng)新互聯(lián)

本篇文章為大家展示了Javascript中怎么實現(xiàn)面向切面編程,內(nèi)容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細(xì)介紹希望你能有所收獲。

10年專注成都網(wǎng)站制作,企業(yè)網(wǎng)站設(shè)計,個人網(wǎng)站制作服務(wù),為大家分享網(wǎng)站制作知識、方案,網(wǎng)站設(shè)計流程、步驟,成功服務(wù)上千家企業(yè)。為您提供網(wǎng)站建設(shè),網(wǎng)站制作,網(wǎng)頁設(shè)計及定制高端網(wǎng)站建設(shè)服務(wù),專注于企業(yè)網(wǎng)站設(shè)計,高端網(wǎng)頁制作,對活動板房等多個領(lǐng)域,擁有豐富的網(wǎng)站設(shè)計經(jīng)驗。

面向切面編程(Aspect-oriented programming,AOP)是一種編程范式。做后端 Java web 的同學(xué),特別是用過 Spring 的同學(xué)肯定對它非常熟悉。AOP 是 Spring 框架里面其中一個重要概念??墒窃?Javascript 中,AOP 是一個經(jīng)常被忽視的技術(shù)點。

場景

假設(shè)你現(xiàn)在有一個牛逼的日歷彈窗,有一天,老板讓你統(tǒng)計一下每天這個彈窗里面某個按鈕的點擊數(shù),于是你在彈窗里做了埋點;

過了一個星期,老板說用戶反饋這個彈窗好慢,各種卡頓。你想看一下某個函數(shù)的平均執(zhí)行時間,于是你又在彈窗里加上了性能統(tǒng)計代碼。

時間久了,你會發(fā)現(xiàn)你的業(yè)務(wù)邏輯里包含了大量的和業(yè)務(wù)無關(guān)的東西,即使是一些你已經(jīng)封裝過的函數(shù)。
那么 AOP 就是為了解決這類問題而存在的。

關(guān)注點分離

分離業(yè)務(wù)代碼和數(shù)據(jù)統(tǒng)計代碼(非業(yè)務(wù)代碼),無論在什么語言中,都是AOP的經(jīng)典應(yīng)用之一。從核心關(guān)注點中分離出橫切關(guān)注點,是 AOP 的核心概念。
在前端的常見需求中,有以下一些業(yè)務(wù)可以使用 AOP 將其從核心關(guān)注點中分離出來

  1. Node.js 日志log

  2. 埋點、數(shù)據(jù)上報

  3. 性能分析、統(tǒng)計函數(shù)執(zhí)行時間

  4. 給ajax請求動態(tài)添加參數(shù)、動態(tài)改變函數(shù)參數(shù)

  5. 分離表單請求和驗證

  6. 防抖與節(jié)流

 裝飾器(Decorator)

提到 AOP 就要說到裝飾器模式,AOP 經(jīng)常會和裝飾器模式混為一談。

在ES6之前,要使用裝飾器模式,通常通過Function.prototype.before做前置裝飾,和Function.prototype.after做后置裝飾(見《Javascript設(shè)計模式和開發(fā)實踐》)。

Javascript 引入的 Decorator ,和 Java 的注解在語法上很類似,不過在語義上沒有一丁點關(guān)系。Decorator 提案提供了對 Javascript 的類和類里的方法進(jìn)行裝飾的能力。(盡管只是在編譯時運行的函數(shù)語法糖)

埋點數(shù)據(jù)上報

因為在使用 React 的實際開發(fā)中有大量基于 Class 的 Component,所以我這里用 React 來舉例。
比如現(xiàn)在頁面中有一個button,點擊這個button會彈出一個彈窗,與此同時要進(jìn)行數(shù)據(jù)上報,來統(tǒng)計有多少用戶點擊了這個登錄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 (
       this.showDialog('show dialog')}>showDialog
    )
  }
}

export default Dialog;

上面代碼引用了@send裝飾器,他會修改這個 Class 上的原型方法,下面是@send裝飾器的實現(xiàn)

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

  descriptor.value = function () {
    console.log(`before calling ${name} with`, arguments);
    return oldValue.apply(this, arguments);
  };

  return descriptor;
}

在按鈕點擊后執(zhí)行showDialog前,可以執(zhí)行我們想要的切面操作,我們可以將埋點,數(shù)據(jù)上報相關(guān)代碼封裝在這個裝飾器里面來實現(xiàn) AOP。

前置裝飾和后置裝飾

上面的send這個裝飾器其實是一個前置裝飾器,我們可以將它再封裝一下使它可以前置執(zhí)行任意函數(shù)。

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

    descriptor.value = function () {
      beforeFn.apply(this, arguments);
      return oldValue.apply(this, arguments);
    };

    return descriptor;
  }
}

這樣我們就可以使用@before裝飾器在一個原型方法前切入任意的非業(yè)務(wù)代碼。

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

和@before裝飾器類似,可以實現(xiàn)一個@after后置裝飾器,只是函數(shù)的執(zhí)行順序不一樣。

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

    descriptor.value = function () {
      let ret = oldValue.apply(this, arguments);
      afterFn.apply(this, arguments);
      return ret;
    };

    return descriptor;
  }
}

性能分析

有時候我們想統(tǒng)計一段代碼在用戶側(cè)的執(zhí)行時間,但是又不想將打點代碼嵌入到業(yè)務(wù)代碼中,同樣可以利用裝飾器來做 AOP。

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

  descriptor.value = function () {
    let ret = oldValue.apply(this, arguments);
    performance.mark("startWork");
    afterFn.apply(this, arguments);
    performance.mark("endWork");
    performance.measure("work", "startWork", "endWork");
    performance
     .getEntries()
     .map(entry => JSON.stringify(entry, null, 2))
     .forEach(json => console.log(json));
    return ret;
  };

  return descriptor;
}

在要統(tǒng)計執(zhí)行時間的類方法前面加上@measure就行了,這樣做性能統(tǒng)計的代碼就不會侵入到業(yè)務(wù)代碼中。

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

上述內(nèi)容就是Javascript中怎么實現(xiàn)面向切面編程,你們學(xué)到知識或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識儲備,歡迎關(guān)注創(chuàng)新互聯(lián)成都網(wǎng)站設(shè)計公司行業(yè)資訊頻道。

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機、免備案服務(wù)器”等云主機租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。


本文名稱:Javascript中怎么實現(xiàn)面向切面編程-創(chuàng)新互聯(lián)
網(wǎng)頁網(wǎng)址:http://weahome.cn/article/dgjssi.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部