最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解在Javascript中進(jìn)行面向切面編程

 更新時(shí)間:2019年04月28日 08:38:06   作者:samciu  
這篇文章主要介紹了Javascript面向切面編程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

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

場(chǎng)景

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

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

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

關(guān)注點(diǎn)分離

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

  1. Node.js 日志log
  2. 埋點(diǎn)、數(shù)據(jù)上報(bào)
  3. 性能分析、統(tǒng)計(jì)函數(shù)執(zhí)行時(shí)間
  4. 給ajax請(qǐng)求動(dòng)態(tài)添加參數(shù)、動(dòng)態(tài)改變函數(shù)參數(shù)
  5. 分離表單請(qǐng)求和驗(yàn)證
  6. 防抖與節(jié)流

 裝飾器(Decorator)

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

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

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

埋點(diǎn)數(shù)據(jù)上報(bào)

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

export default Dialog;

上面代碼引用了@send裝飾器,他會(huì)修改這個(gè) Class 上的原型方法,下面是@send裝飾器的實(shí)現(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;
}

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

前置裝飾和后置裝飾

上面的send這個(gè)裝飾器其實(shí)是一個(gè)前置裝飾器,我們可以將它再封裝一下使它可以前置執(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裝飾器在一個(gè)原型方法前切入任意的非業(yè)務(wù)代碼。

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

和@before裝飾器類似,可以實(shí)現(xiàn)一個(gè)@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;
  }
}

性能分析

有時(shí)候我們想統(tǒng)計(jì)一段代碼在用戶側(cè)的執(zhí)行時(shí)間,但是又不想將打點(diǎn)代碼嵌入到業(yè)務(wù)代碼中,同樣可以利用裝飾器來(lái)做 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)計(jì)執(zhí)行時(shí)間的類方法前面加上@measure就行了,這樣做性能統(tǒng)計(jì)的代碼就不會(huì)侵入到業(yè)務(wù)代碼中。

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

小結(jié)

面向切面編程的重點(diǎn)就是將核心關(guān)注面分離出橫切關(guān)注面,前端可以用 AOP 優(yōu)雅的來(lái)組織數(shù)據(jù)上報(bào)、性能分析、統(tǒng)計(jì)函數(shù)的執(zhí)行時(shí)間、動(dòng)態(tài)改變函數(shù)參數(shù)、插件式的表單驗(yàn)證等代碼。

以上所述是小編給大家介紹的Javascript面向切面編程詳解整合,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!

相關(guān)文章

  • layui前端時(shí)間戳轉(zhuǎn)化實(shí)例

    layui前端時(shí)間戳轉(zhuǎn)化實(shí)例

    今天小編就為大家分享一篇layui前端時(shí)間戳轉(zhuǎn)化實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-11-11
  • css3元素簡(jiǎn)單的閃爍效果實(shí)現(xiàn)(html5 jquery)

    css3元素簡(jiǎn)單的閃爍效果實(shí)現(xiàn)(html5 jquery)

    本篇文章主要介紹了css3元素簡(jiǎn)單的閃爍效果實(shí)現(xiàn)(html5 jquery) 需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助
    2013-12-12
  • 聊一聊JS中的prototype

    聊一聊JS中的prototype

    function定義的對(duì)象有一個(gè)prototype屬性,prototype屬性又指向了一個(gè)prototype對(duì)象,注意prototype屬性與prototype對(duì)象是兩個(gè)不同的東西,要注意區(qū)別.這篇文章主要介紹了JS中的prototype的相關(guān)資料,需要的朋友可以參考下
    2016-09-09
  • js對(duì)象基礎(chǔ)實(shí)例分析

    js對(duì)象基礎(chǔ)實(shí)例分析

    這篇文章主要介紹了js對(duì)象基礎(chǔ),以實(shí)例形式分析了js對(duì)象的創(chuàng)建、讀取及遍歷等技巧,需要的朋友可以參考下
    2015-01-01
  • JS從數(shù)組中隨機(jī)取出幾個(gè)數(shù)組元素的方法

    JS從數(shù)組中隨機(jī)取出幾個(gè)數(shù)組元素的方法

    JS如何從一個(gè)數(shù)組中隨機(jī)取出一個(gè)元素或者幾個(gè)元素呢?其實(shí)方法很簡(jiǎn)單,下面小編給大家分享了JS隨機(jī)取出幾個(gè)數(shù)組元素的方法,非常不錯(cuò),需要的朋友參考下
    2016-08-08
  • js實(shí)現(xiàn)圖片粘貼到網(wǎng)頁(yè)

    js實(shí)現(xiàn)圖片粘貼到網(wǎng)頁(yè)

    這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)圖片粘貼到網(wǎng)頁(yè),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • JavaScript中的object轉(zhuǎn)換函數(shù)toString()與valueOf()介紹

    JavaScript中的object轉(zhuǎn)換函數(shù)toString()與valueOf()介紹

    這篇文章主要介紹了JavaScript中的object轉(zhuǎn)換函數(shù)toString()與valueOf()介紹,需要的朋友可以參考下
    2014-12-12
  • 微信小程序?qū)崿F(xiàn)帶縮略圖輪播效果

    微信小程序?qū)崿F(xiàn)帶縮略圖輪播效果

    這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)帶縮略圖的輪播效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-11-11
  • Javascript將JSON日期格式化

    Javascript將JSON日期格式化

    在做項(xiàng)目中,將實(shí)體轉(zhuǎn)化為JSON后,結(jié)果后臺(tái)返回json時(shí)間格式為/Date(1306418993027)/,在前臺(tái)JS里顯示的并不是真正的日期,而且我們不能把所有日期字段都變成string吧,因此寫了Javascript的擴(kuò)展方法,來(lái)實(shí)現(xiàn)這個(gè)功能,代碼如下
    2016-08-08
  • js實(shí)現(xiàn)圖片左右滾動(dòng)效果

    js實(shí)現(xiàn)圖片左右滾動(dòng)效果

    本文主要介紹了js實(shí)現(xiàn)圖片左右滾動(dòng)效果的實(shí)例,具有很好的參考價(jià)值,下面跟著小編一起來(lái)看下吧
    2017-02-02

最新評(píng)論

太仆寺旗| 黔东| 台中市| 上栗县| 西乡县| 平谷区| 沛县| 长阳| 金沙县| 收藏| 浏阳市| 鹰潭市| 饶阳县| 尚义县| 新密市| 喀喇沁旗| 鄂托克前旗| 普兰店市| 江口县| 库伦旗| 湖北省| 大理市| 济宁市| 贞丰县| 南丹县| 太谷县| 新安县| 开化县| 青川县| 田林县| 崇仁县| 定安县| 马尔康县| 武安市| 兰溪市| 开原市| 镶黄旗| 尖扎县| 康保县| 五指山市| 驻马店市|