ES7之裝飾器瞭解一下

ES7之裝飾器

恰好最近在弄 TypeScript ,不少用到裝飾器 因此就從基礎開始看起.javascript

基礎環境配置

  1. yarn add @babel/cli -g
  2. 建立.babelrc
  3. yarn add @babel/plugin-proposal-class-properties --save-dev
  4. yarn add @babel/plugin-proposal-decorators --savde-dev
  5. yarn add @babel/preset-env --savde-dev

常規操做

class Decoration {
constructor() {
this.keyValue = ""
}
@statement // 裝飾器命名
url = 'aaa'; //被裝飾的屬性
agent() {
console.log( this.url,'-------------' ,this.keyValue);
}
}

function statement(proto, key, descriptor){
console.log('sdsdsd',proto, key, descriptor);
descriptor.writable = false; //被裝飾屬性不可寫
}

複製代碼

對屬性作裝飾

class Decoration {
constructor() {
this.value = ""
}
@statement // 裝飾器命名
url = 'sjh'; //被裝飾的屬性
agent() {
console.log( this.url,'+++' ,this.value);
}
}

function statement(proto, key, descriptor) {
console.log('sdsdsd',proto, key, descriptor);

descriptor.writable = true
// console.log(descriptor.initializer()) //被裝飾的屬性值;裝飾私有屬性特有的一個屬性

descriptor.initializer = function () {
return 'url的值被修改了'
}
}

var os = new Decoration();
console.log(os.agent());

// 解析 輸出
{constructor: ƒ, agent: ƒ}
url
{configurable: true, enumerable: true, writable: true, initializer: ƒ}
url的值被修改了 ------ undefined
statement裝飾器做用於 url
咱們定義的function statement有個 initializer方法 將值作了修改 initializerbabel內部是用來建立對象屬性的屬性描述符 複製代碼

對原型作裝飾

class Decoration {
constructor() {
this.value = "";
}
url='1'
@pro //裝飾原型方法
agent() {
console.log(this.url + "++" + this.value);
}
}

function pro(proto, key, descriptor){
console.log(proto, key, descriptor)//打印結果以下;
let oldValue = descriptor.value //被裝飾的函數
descriptor.value = function(){
console.log('被裝飾的函數重寫')
}
}

var os = new Decoration();
os.agent()


輸出:
{constructor: ƒ, agent: ƒ}
"agent"
{value: ƒ, writable: true, enumerable: false, configurable: true}
被裝飾的函數重寫


複製代碼

裝飾類

class Decoration {
constructor() {
this.value = "";
}
@skin
agent() {
console.log(this.value + "----------" + this.age);
}
}

function skin(traget) {
traget.age = '18' //添加一個屬性age並賦值18
}

var os = new Decoration();
os.agent();

輸出 this.age

複製代碼

實現proxy劫持

class C {
constructor(){
this.children ='1'
}
@enumerable(false)
get method() {
return this.children.length;
}
}

function enumerable(value) {
return function (target, key, descriptor) {
descriptor.enumerable = value;
return descriptor;
}
}

var c = new C();
c.method();


複製代碼

實現一個memoized方法

class Person {
@memoize
get name() { return `${this.first} ${this.last}` }
set name(val) {
let [first, last] = val.split(' ');
this.first = first;
this.last = last;
}
}

let memoized = new WeakMap();
function memoize(target, name, descriptor) {
let getter = descriptor.get, setter = descriptor.set;

descriptor.get = function() {
let table = memoizationFor(this);
if (name in table) { return table[name]; }
return table[name] = getter.call(this);
}

descriptor.set = function(val) {
let table = memoizationFor(this);
setter.call(this, val);
table[name] = val;
}
}

function memoizationFor(obj) {
let table = memoized.get(obj);
if (!table) { table = Object.create(null); memoized.set(obj, table); }
return table;
}

複製代碼

裝飾器在TypeScript中的運用

裝飾是一種特殊種類的聲明可被做用於一個類聲明、方法、訪問器,屬性或參數。其用法與 ES7 無太大差異。
function f() {
console.log("f(): evaluated");
return function (target, propertyKey: string, descriptor: PropertyDescriptor) {
console.log("f(): called");
}
}

function g() {
console.log("g(): evaluated");
return function (target, propertyKey: string, descriptor: PropertyDescriptor) {
console.log("g(): called");
}
}

class C {
@f()
@g()
method() {}
}
複製代碼

typescript 要注意的點

注意TypeScript不容許爲單個成員裝飾get和set訪問器。相反,成員的全部裝飾器必須應用於以文檔順序指定的第一個訪問器。這是由於裝飾器適用於屬性描述符,該屬性描述符組合了訪問器get和set訪問器,而不是單獨的每一個聲明。java

class Point {
private _x: number;
private _y: number;
constructor(x: number, y: number) {
this._x = x;
this._y = y;
}

@configurable(false)
get x() { return this._x; }

@configurable(false)
get y() { return this._y; }
}

function configurable(value: boolean) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
descriptor.configurable = value;
};
}

複製代碼

裝飾器不能用於函數

var counter = 0;

var add = function() {
    counter++;
};

@add
function foo() {}
複製代碼

後記

歡迎關注微信公衆號!,進行更好的交流。
複製代碼

微信
相關文章
相關標籤/搜索