摘要:面向切面編程嗯,百度百科一下為的縮寫,意為面向切面編程,通過預編譯方式和運行期動態(tài)代理實現(xiàn)程序功能的統(tǒng)一維護的一種技術。
面向切面編程
~~~~ 嗯,百度百科一下 ~~~~
AOP 為 Aspect Oriented Programming 的縮寫,意為:面向切面編程,通過預編譯方式和運行期動態(tài)代理實現(xiàn)程序功能的統(tǒng)一維護的一種技術。AOP 是 OOP 的延續(xù),是軟件開發(fā)中的一個熱點,也是 Spring 框架中的一個重要內容,是函數(shù)式編程的一種衍生范型。利用 AOP 可以對業(yè)務邏輯的各個部分進行隔離,從而使得業(yè)務邏輯各部分之間的耦合度降低,提高程序的可重用性,同時提高了開發(fā)的效率。
作為前端的小萌理解為,就是將除主流程外的其他業(yè)務剝離出來,然后從側面切入。對原功能無侵入式的修改。
話不多說,來個網(wǎng)上的經典例子:
業(yè)務邏輯:
主業(yè)務:修改數(shù)據(jù)庫
切入點 1:修改前打印日志
切入點 2:修改后打印日志
Function.prototype.before = function(beforeFunc) { let that = this return function() { beforeFunc.apply(this, arguments) return that.apply(this, arguments) } } Function.prototype.after = function(afterFunc) { let that = this return function() { let ret = that.apply(this, arguments) afterFunc.apply(this, arguments) return ret } } function updateDb() { console.log(`update db`) } function beforeUpdateDb() { console.log(`before update db`) } function afterUpdateDb() { console.log(`updated db`) } updateDb = updateDb.before(beforeUpdateDb).after(afterUpdateDb) updateDb()
原理:其實就是將主業(yè)務updateDb包裹2次,返回一個新的方法。新方法會在原方法調用前后調用切入方法,避免在主方法上直接改動。
這樣的可讀性和代碼維護性是不是很差,下面用裝飾器看看如何實現(xiàn)切面編程,
裝飾器 decorator裝飾器是ES7現(xiàn)代游覽器并不兼容,需要babel轉譯,插件(babel-plugin-transform-decorators-legacy)
裝飾器只能作用于類本身、類的方法或屬性、訪問操作符
修飾器“@”為標識符
1 對類的裝飾@create class Apes { } // 修飾類本身 function create(className) { className.prototype.create = function() { console.log("制造工具") } return descriptor } let apes1 = new Apes() apes1.create() // 制造工具
對類本身修飾:create(className)。裝飾器本質就是編譯時執(zhí)行的函數(shù)。
要修飾子類,通過要className.prototype修飾子類。
2 對類的方法修飾class Apes { @eatMore eat() { console.log("吃水果") } } // 修飾方法 function eatMore(className, propName, descriptor) { //console.log(descriptor) let value = descriptor.value descriptor.value = function() { console.log("吃土") value() } return descriptor } let apes1 = new Apes() apes1.eat()
對類的方法裝飾 eatMore(className, propName, descriptor)
className - 被修飾的類 propName - 被修飾的屬性名 descriptor - 該屬性的描述對象
通過descriptor屬性描述符看出 依賴于ES5的Object.defineProperty
復習一下Object.defineProperty
value:屬性的值,默認為undefined writable:能否修改屬性的值,默認值為true enumerable:能否通過for-in循環(huán)返回屬性。默認為ture configurable:能否通過delete刪除屬性從而重新定義屬性,能否修改屬性的特性,能否把屬性修改為訪問器屬性,默認為true.
上面對類的方法修飾 實際是通過 descriptor.value 拿到其方法,在進行包裝返回
同時也可以直接修改descriptor上的其他屬性或者返回一個新的descriptor
3. 針對 訪問操作符的裝飾class test { //@nonenumerable get kidCount() { return 111 } } function disWirte(target, name, descriptor) { descriptor.writable = false return descriptor } let p = new test() console.log(p.kidCount) p.kidCount = 222n descriptor; // 拋出異常 // TypeError: Cannot set property kidCount of #4. 修飾傳參which has only a getter
class Apes { @say("可以說漢語了") say() { console.log("厵爨癵驫寶麣纞虋讟钃鸜麷鞻韽顟顠饙饙騳騱龗鱻爩麤") } } // 修飾方法并傳遞參數(shù) function say(str) { return function(className, propName, descriptor) { descriptor.value = function() { console.log(str) } return descriptor } }
通過柯里化的方式傳遞參數(shù)
應用 1. 應用在斐波那契數(shù)列計算中const memory = () => { const cache = {} //緩存池 return (target, name, descriptor) => { // 原方法 const method = descriptor.value // 包裹原方法 descriptor.value = function(key) { if (cache[key]) { return cache[key] } const ret = method.apply(target, [key]) cache[key] = ret return ret } return descriptor } } let count = 0 class Test { @memory() fb(n) { count++ if (n === 1) return 1 if (n === 2) return 1 return this.fb(n - 1) + this.fb(n - 2) } } const t = new Test() console.log(t.fb(10)) console.log(count)2. 訪問操作符-set 上作類型檢查
class test { constructor() { this.a = 1 } get a() { return this.a } @check("number") set a(v) { return v } } function check(type) { return function(target, prop, descriptor) { let v = descriptor.value return { enumerable: true, configurable: true, get: function() { return v }, set: function(c) { var curType = typeCheck(c) if (curType !== type) { throw `${prop}必須為${type}類型` } v = c } } } } function typeCheck(c) { if (c === undefined) { return undefined } if (c === null) { return null } let type = typeof c if (type === "object") { return c.constructor == Array ? "array" : "object" } return type } let t = new test(11) t.a = 2 console.log(t.a) // 2 t.a = [] console.log(t.a) // throw a必須為number類型
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/106576.html
摘要:中的裝飾在前端編程中,我們可以采用裝飾器,來實現(xiàn)編程。裝飾器使用我們先建立一個簡單的類,這個類的作用,就是在執(zhí)行的時候,打印出。至此,一個簡單的裝飾器范例已經完成。 什么是裝飾器? 了解AOP 在學習js中的裝飾器之間,我們需要了解AOP(面向切面編程)編程思想。 AOP是一種可以通過預編譯方式和運行期動態(tài)代理實現(xiàn)在不修改源代碼的情況下給程序動態(tài)統(tǒng)一添加功能的一種技術。AOP實際是Go...
摘要:項目地址項目主頁基于和注解的輕量級容器,提供了依賴注入面向切面編程及異常處理等功能。可在任意工程中引入,是一個框架無關的容器。模塊不依賴于任何框架,并與現(xiàn)有框架庫類等保持兼容。 Rockerjs Core 項目地址 項目主頁 基于 TypeScript 和注解的輕量級IoC容器,提供了依賴注入、面向切面編程及異常處理等功能。Rockerjs Core可在任意工程中引入,是一個框架無...
摘要:項目地址項目主頁基于和注解的輕量級容器,提供了依賴注入面向切面編程及異常處理等功能。可在任意工程中引入,是一個框架無關的容器。模塊不依賴于任何框架,并與現(xiàn)有框架庫類等保持兼容。 Rockerjs Core 項目地址 項目主頁 基于 TypeScript 和注解的輕量級IoC容器,提供了依賴注入、面向切面編程及異常處理等功能。Rockerjs Core可在任意工程中引入,是一個框架無...
摘要:下裝飾者的實現(xiàn)了解了裝飾者模式和的概念之后,我們寫一段能夠兼容的代碼來實現(xiàn)裝飾者模式原函數(shù)拍照片定義函數(shù)裝飾函數(shù)加濾鏡用裝飾函數(shù)裝飾原函數(shù)這樣我們就實現(xiàn)了抽離拍照與濾鏡邏輯,如果以后需要自動上傳功能,也可以通過函數(shù)來添加。 showImg(https://segmentfault.com/img/bVbueyz?w=852&h=356); 什么是裝飾者模式 當我們拍了一張照片準備發(fā)朋友...
摘要:裝飾器顧名思義就是裝飾某種東西的方法,可以用來裝飾屬性變量函數(shù)類實例方法本質上是個函數(shù)。以符開頭,函數(shù)名稱自擬。愛吃蘋果裝飾器裝飾類愛吃蘋果結果是這個類本身就可以通過修改類的屬性增加屬性被裝飾的對象可以使用多個裝飾器。 @Decorator 裝飾器是es7的語法,這個方法對于面向切面編程有了更好的詮釋,在一些情境中可以使用,比如路人A的代碼實現(xiàn)了一需求,路人B希望用A的方法來實現(xiàn)一個新...
閱讀 3728·2021-11-24 09:39
閱讀 2609·2019-08-30 15:54
閱讀 1149·2019-08-30 13:01
閱讀 3429·2019-08-28 18:30
閱讀 1622·2019-08-26 17:44
閱讀 3591·2019-08-26 11:31
閱讀 2413·2019-08-26 10:40
閱讀 1239·2019-08-26 10:27