TypeScript 装饰器实现原理剖析 All In One
TypeScript 装饰器实现原理剖析 All In One
TypeScript @Decorator
function first() {
console.log("first(): factory evaluated");
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
console.log("first(): called");
};
}
function second() {
console.log("second(): factory evaluated");
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
console.log("second(): called");
};
}
class ExampleClass {
@first()
@second()
method() {}
}
/*
first(): factory evaluated
second(): factory evaluated
second(): called
first(): called
*/
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
// @experimentalDecorators
function first() {
console.log("first(): factory evaluated");
return function (target, propertyKey, descriptor) {
console.log("first(): called");
};
}
function second() {
console.log("second(): factory evaluated");
return function (target, propertyKey, descriptor) {
console.log("second(): called");
};
}
class ExampleClass {
method() { }
}
__decorate([
first(),
second(),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", void 0)
], ExampleClass.prototype, "method", null);
https://www.typescriptlang.org/docs/handbook/decorators.html
Object.defineProperty()
数据双向绑定,数据拦截,变化监听
const log = console.log;
const obj = {};
// Object.defineProperty(obj, prop, descriptor)
Object.defineProperty(obj, 'prop', {
// value: undefined,
value: 2022,
// writable: false,
writable: true,
// enumerable: false,
enumerable: true,
// configurable: false,
configurable: true,
// accessors
// get: undefined,
// set: undefined,
});
// Error: Invalid property descriptor. Cannot both specify accessors and a value or writable attribute, #<Object>
console.log(obj);
obj.prop = 2048;
// "use-strict";throws an error in strict mode
console.log(obj.prop);
// 2022
Object.defineProperties()
const log = console.log;
const obj = {};
Object.defineProperties(obj, {
prop: {
value: 2022,
writable: false,
},
skills: {
value: ['TypeScript', 'JavaScript', 'HTML5'],
writable: true,
},
});
log(obj);
log(obj.prop);
log(obj.skills);
/*
Object { }
2022
Array ["TypeScript", "JavaScript", "HTML5"]
*/
Object.getOwnPropertyDescriptor()
const log = console.log;
const obj = {
prop: 2022,
name: 'xgqfrms',
skills: ['TypeScript', 'JavaScript', 'HTML5'],
};
const descriptor = Object.getOwnPropertyDescriptor(obj, 'prop');
const skills = Object.getOwnPropertyDescriptor(obj, 'skills');
log(descriptor);
// Object { value: 2022, writable: true, enumerable: true, configurable: true }
log(skills);
// Object { value: Array ["TypeScript", "JavaScript", "HTML5"], writable: true, enumerable: true, configurable: true }
log(descriptor.configurable);
log(descriptor.enumerable);
log(descriptor.writable);
// true
// true
// true
log(descriptor.value);
log(descriptor.get);
log(descriptor.set);
// 2022
// undefined
// undefined
property descriptor
A property descriptor is a record with some of the following attributes:
-
value
The value associated with the property (data descriptors only). -
writable
true if and only if the value associated with the property may be changed (data descriptors only). -
configurable
true if and only if the type of this property descriptor may be changed and if the property may be deleted from the corresponding object. -
enumerable
true if and only if this property shows up during enumeration of the properties on the corresponding object. -
get
A function which serves as a getter for the property, or undefined if there is no getter (accessor descriptors only). -
set
A function which serves as a setter for the property, or undefined if there is no setter (accessor descriptors only).
Record
Record<Keys, Type>
interface CatType {
age: number;
breed: string;
}
type CatName = "miffy" | "boris" | "mordred";
const cats: Record<CatName, CatType> = {
miffy: { age: 10, breed: "Persian" },
boris: { age: 5, breed: "Maine Coon" },
mordred: { age: 16, breed: "British Shorthair" },
};
cats.boris;
// ^? const cats: Record<CatName, CatInfo>
"use strict";
const cats = {
miffy: { age: 10, breed: "Persian" },
boris: { age: 5, breed: "Maine Coon" },
mordred: { age: 16, breed: "British Shorthair" },
};
cats.boris;
// ^?
https://www.typescriptlang.org/docs/handbook/utility-types.html#recordkeys-type
https://www.typescriptlang.org/play
refs
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object
©xgqfrms 2012-2020
www.cnblogs.com/xgqfrms 发布文章使用:只允许注册用户才可以访问!
原创文章,版权所有©️xgqfrms, 禁止转载 🈲️,侵权必究⚠️!
本文首发于博客园,作者:xgqfrms,原文链接:https://www.cnblogs.com/xgqfrms/p/15881686.html
未经授权禁止转载,违者必究!