在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称:wycats/javascript-decorators开源软件地址:https://github.com/wycats/javascript-decorators开源编程语言:开源软件介绍:This has moved to https://github.com/tc39/proposal-decorators SummaryDecorators make it possible to annotate and modify classes and properties at design time. While ES5 object literals support arbitrary expressions in the value position, ES6 classes only support literal functions as values. Decorators restore the ability to run code at design time, while maintaining a declarative syntax. Detailed DesignA decorator is:
Consider a simple class definition: class Person {
name() { return `${this.first} ${this.last}` }
} Evaluating this class results in installing the Object.defineProperty(Person.prototype, 'name', {
value: specifiedFunction,
enumerable: false,
configurable: true,
writable: true
}); A decorator precedes the syntax that defines a property: class Person {
@readonly
name() { return `${this.first} ${this.last}` }
} Now, before installing the descriptor onto let description = {
type: 'method',
initializer: () => specifiedFunction,
enumerable: false,
configurable: true,
writable: true
};
description = readonly(Person.prototype, 'name', description) || description;
defineDecoratedProperty(Person.prototype, 'name', description);
function defineDecoratedProperty(target, { initializer, enumerable, configurable, writable }) {
Object.defineProperty(target, { value: initializer(), enumerable, configurable, writable });
} The has an opportunity to intercede before the relevant A decorator that precedes syntactic getters and/or setters operates on an accessor description: class Person {
@nonenumerable
get kidCount() { return this.children.length; }
}
let description = {
type: 'accessor',
get: specifiedGetter,
enumerable: true,
configurable: true
}
function nonenumerable(target, name, description) {
descriptor.enumerable = false;
return descriptor;
} A more detailed example illustrating a simple decorator that memoizes an accessor. 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;
} It is also possible to decorate the class itself. In this case, the decorator takes the target constructor. // A simple decorator
@annotation
class MyClass { }
function annotation(target) {
// Add a property on target
target.annotated = true;
} Since decorators are expressions, decorators can take additional arguments and act like a factory. @isTestable(true)
class MyClass { }
function isTestable(value) {
return function decorator(target) {
target.isTestable = value;
}
} The same technique could be used on property decorators: class C {
@enumerable(false)
method() { }
}
function enumerable(value) {
return function (target, key, descriptor) {
descriptor.enumerable = value;
return descriptor;
}
} Because descriptor decorators operate on targets, they also naturally work on
static methods. The only difference is that the first argument to the decorator
will be the class itself (the constructor) rather than the prototype, because
that is the target of the original For the same reason, descriptor decorators work on object literals, and pass the object being created to the decorator. DesugaringClass DeclarationSyntax@F("color")
@G
class Foo {
} Desugaring (ES6)var Foo = (function () {
class Foo {
}
Foo = F("color")(Foo = G(Foo) || Foo) || Foo;
return Foo;
})(); Desugaring (ES5)var Foo = (function () {
function Foo() {
}
Foo = F("color")(Foo = G(Foo) || Foo) || Foo;
return Foo;
})(); Class Method DeclarationSyntaxclass Foo {
@F("color")
@G
bar() { }
} Desugaring (ES6)var Foo = (function () {
class Foo {
bar() { }
}
var _temp;
_temp = F("color")(Foo.prototype, "bar",
_temp = G(Foo.prototype, "bar",
_temp = Object.getOwnPropertyDescriptor(Foo.prototype, "bar")) || _temp) || _temp;
if (_temp) Object.defineProperty(Foo.prototype, "bar", _temp);
return Foo;
})(); Desugaring (ES5)var Foo = (function () {
function Foo() {
}
Foo.prototype.bar = function () { }
var _temp;
_temp = F("color")(Foo.prototype, "bar",
_temp = G(Foo.prototype, "bar",
_temp = Object.getOwnPropertyDescriptor(Foo.prototype, "bar")) || _temp) || _temp;
if (_temp) Object.defineProperty(Foo.prototype, "bar", _temp);
return Foo;
})(); Class Accessor DeclarationSyntaxclass Foo {
@F("color")
@G
get bar() { }
set bar(value) { }
} Desugaring (ES6)var Foo = (function () {
class Foo {
get bar() { }
set bar(value) { }
}
var _temp;
_temp = F("color")(Foo.prototype, "bar",
_temp = G(Foo.prototype, "bar",
_temp = Object.getOwnPropertyDescriptor(Foo.prototype, "bar")) || _temp) || _temp;
if (_temp) Object.defineProperty(Foo.prototype, "bar", _temp);
return Foo;
})(); Desugaring (ES5)var Foo = (function () {
function Foo() {
}
Object.defineProperty(Foo.prototype, "bar", {
get: function () { },
set: function (value) { },
enumerable: true, configurable: true
});
var _temp;
_temp = F("color")(Foo.prototype, "bar",
_temp = G(Foo.prototype, "bar",
_temp = Object.getOwnPropertyDescriptor(Foo.prototype, "bar")) || _temp) || _temp;
if (_temp) Object.defineProperty(Foo.prototype, "bar", _temp);
return Foo;
})(); Object Literal Method DeclarationSyntaxvar o = {
@F("color")
@G
bar() { }
} Desugaring (ES6)var o = (function () {
var _obj = {
bar() { }
}
var _temp;
_temp = F("color")(_obj, "bar",
_temp = G(_obj, "bar",
_temp = void 0) || _temp) || _temp;
if (_temp) Object.defineProperty(_obj, "bar", _temp);
return _obj;
})(); Desugaring (ES5)var o = (function () {
var _obj = {
bar: function () { }
}
var _temp;
_temp = F("color")(_obj, "bar",
_temp = G(_obj, "bar",
_temp = void 0) || _temp) || _temp;
if (_temp) Object.defineProperty(_obj, "bar", _temp);
return _obj;
})(); Object Literal Accessor DeclarationSyntaxvar o = {
@F("color")
@G
get bar() { }
set bar(value) { }
} Desugaring (ES6)var o = (function () {
var _obj = {
get bar() { }
set bar(value) { }
}
var _temp;
_temp = F("color")(_obj, "bar",
_temp = G(_obj, "bar",
_temp = void 0) || _temp) || _temp;
if (_temp) Object.defineProperty(_obj, "bar |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论