ECMAScript Decorators---裝飾器
Decorators是什么
- Decorators可以改變類(lèi)方法和類(lèi)實(shí)例字段的屬性和行為,使我們可以靈活地使用更簡(jiǎn)單的語(yǔ)法動(dòng)態(tài)實(shí)現(xiàn)這些內(nèi)容,是非侵入式的。---舉例,你給手機(jī)添加一個(gè)外殼罷了,并不影響手機(jī)原有的通話(huà)、充電等功能
應(yīng)用場(chǎng)景
- Decorators的經(jīng)典的應(yīng)用是AOP編程,比如“日志系統(tǒng)”,日志系統(tǒng)的作用是記錄系統(tǒng)的行為操作,它在不影響原有系統(tǒng)的功能的基礎(chǔ)上增加記錄環(huán)節(jié)
- 更加抽象的理解,可以理解為給數(shù)據(jù)流做一層filter,因此 AOP 的典型應(yīng)用包括安全檢查、緩存、調(diào)試、持久化等等。
原理
- Decorators的本質(zhì)是利用了ES5的Object.defineProperty屬性,這三個(gè)參數(shù)其實(shí)是和Object.defineProperty參數(shù)一致的,因此不能更改
- object 必需。要在其上添加或修改屬性的對(duì)象 這可能是一個(gè)本機(jī)JavaScript對(duì)象(即用戶(hù)定義的對(duì)象或內(nèi)置對(duì)象)或 DOM 對(duì)象。
- propertyname必需。一個(gè)包含屬性名稱(chēng)的字符串
- descriptor 必需。 屬性描述符。它可以針對(duì)數(shù)據(jù)屬性或訪(fǎng)問(wèn)器屬性。
- 舉例說(shuō)明
var myObj = {myPropOne: 1,myPropTwo: 2
};
// modify property descriptor
Object.defineProperty( myObj,
'myPropOne', {writable:
false, // 是否允許該屬性值更改enumerable:
false, // 是否允許key被枚舉,話(huà)句話(huà)說(shuō)
for in 或者Object.keys() 不會(huì)輸出keyconfigurable:
false// 目標(biāo)屬性是否可以被刪除或是否可以再次修改特性
} );
應(yīng)用舉例
類(lèi)方法 @readonly
class User {constructor( firstname, lastName ) {this.firstname = firstname;this.lastName = lastName;}@
readonlygetFullName() {
return this.firstname
' ' this.lastName;}
}
// create instance
let user = new User(
'John',
'Doe' );
console.log( user.getFullName() );// 某天我不小心重寫(xiě)了這個(gè)方法
User.prototype.getFullName =
function() {
return 'HACKED!';
}// 輸出 HACKED! 與預(yù)期不符,怎么避免此類(lèi)情況發(fā)生// 方法1 這是最好的解決方案么?修飾器登場(chǎng)
Object.defineProperty( User.prototype,
'getFullName', {writable:
false
});// 將此方法添加到修飾方法getFullName上
function readonly( target, property, descriptor ) {descriptor.writable =
false;
return descriptor;
}
類(lèi)方法 @log日志打印
function log(
logMessage ) {//
return decorator
functionreturn function ( target, property, descriptor ) {// save original value,
which is method (
function)
let originalMethod = descriptor.value;// replace method implementationdescriptor.value =
function( ...args ) {console.log(
'[LOG]',
logMessage );// here, call original method// `this` points to the instance
return originalMethod.call( this, ...args );};
return descriptor;}
}
class User {constructor( firstname, lastName ) {this.firstname = firstname;this.lastName = lastName;}@
log(
'calling getFullName method on User class')
getFullName() {
return this.firstname
' ' this.lastName;}
}
var user = new User(
'John',
'Doe' );
console.log( user.getFullName() );
類(lèi)的屬性 大小寫(xiě)轉(zhuǎn)換
// 解釋:descriptor.initializer函數(shù)由Babel內(nèi)部使用來(lái)創(chuàng)建對(duì)象屬性的屬性描述符的值
function toCase( CASE =
'lower' ) {
return function ( target, name, descriptor ) {
let initValue = descriptor.initializer();descriptor.initializer =
function(){
return ( CASE ==
'lower' ) ? initValue.toLowerCase() : initValue.toUpperCase();}
return descriptor;}
}
class User {@toCase(
'upper' )firstName =
'default_first_name';lastName =
'default_last_name';constructor( firstName, lastName ) {
if( firstName ) this.firstName = firstName;
if( lastName ) this.lastName = lastName;}
getFullName() {
return this.firstName
' ' this.lastName;}
}
console.log( new User() );
類(lèi)裝飾器
function withLoginStatus( UserRef ) {
return class extends UserRef {constructor( ...args ) {super( ...args );this.isLoggedIn =
false;}
setLoggedIn() {this.isLoggedIn =
true;}}
}
@withLoginStatus
class User {constructor( firstName, lastName ) {this.firstName = firstName;this.lastName = lastName;}
}
let user = new User(
'John',
'Doe' );
console.log(
'Before ===> ', user );
//
set logged
in
user.setLoggedIn();
console.log(
'After ===> ', user );
babel 裝換
- 在線(xiàn)轉(zhuǎn)換鏈接(如無(wú)法打開(kāi)網(wǎng)頁(yè)需翻墻)
- 構(gòu)建babel裝換
1、創(chuàng)建項(xiàng)目文件
2、命令行進(jìn)入該項(xiàng)目目錄 npm init
3、npm install babel-core babel-plugin-transform-decorators
4、安裝 npm install babel-plugin-transform-decorators-legacy --save-dev
5、.babelrc添加
{
"plugins": [
"transform-decorators-legacy"]
}
參考鏈接
- ECMAScript Decorators---裝飾器
- ES7 Decorator 裝飾者模式
- 阮一峰---修飾器
總結(jié)
以上是生活随笔為你收集整理的ECMAScript Decorators---装饰器的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。