xgqfrms™, xgqfrms® : xgqfrms's offical website of cnblogs! xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!

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


https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

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"]
*/

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperties

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:

  1. value
    The value associated with the property (data descriptors only).

  2. writable
    true if and only if the value associated with the property may be changed (data descriptors only).

  3. 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.

  4. enumerable
    true if and only if this property shows up during enumeration of the properties on the corresponding object.

  5. get
    A function which serves as a getter for the property, or undefined if there is no getter (accessor descriptors only).

  6. set
    A function which serves as a setter for the property, or undefined if there is no setter (accessor descriptors only).

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptor

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, 禁止转载 🈲️,侵权必究⚠️!


posted @ 2022-02-11 01:21  xgqfrms  阅读(94)  评论(6编辑  收藏  举报