Convidamos futuros alunos do curso "JavaScript Developer. Professional" a se inscreverem em uma aula aberta sobre o tema "Fazendo um bot de telegrama interativo em Node.js" .
E agora estamos compartilhando a tradução tradicional de material útil.
Compreendendo as funções do decorador
O que é um decorador?
Um decorador é um recurso que permite envolver uma função em outra e estender seus recursos. Você "decora" o código existente envolvendo-o em outro código. Esse truque é familiar para qualquer pessoa familiarizada com a composição de funções ou funções de ordem superior.
Decoradores não são novos. Eles também são usados em outras linguagens, como Python, e até mesmo em programação funcional em JavaScript. Mas falaremos sobre isso mais tarde.
Por que precisamos de decoradores?
Eles permitem que você escreva um código mais limpo, adira ao conceito de composição e estenda uma capacidade desenvolvida uma vez para várias funções e classes. Usando decoradores, você pode escrever código mais fácil de depurar e manter.
, , , . , .
2- , .
, .
Bit Node, TypeScript, React, Vue, Angular JS.

?
— . , -. -, . , .
?
.
— . , Java, , , . JavaScript , . , .
, . , , , .
, , .
//decorator function
const allArgsValid = function(fn) {
return function(...args) {
if (args.length != fn.length) {
throw new Error('Only submit required number of params');
}
const validArgs = args.filter(arg => Number.isInteger(arg));
if (validArgs.length < fn.length) {
throw new TypeError('Argument cannot be a non-integer');
}
return fn(...args);
}
}
//ordinary multiply function
let multiply = function(a,b){
return a*b;
}
//decorated multiply function that only accepts the required number of params and only integers
multiply = allArgsValid(multiply);
multiply(6, 8);
//48
multiply(6, 8, 7);
//Error: Only submit required number of params
multiply(3, null);
//TypeError: Argument cannot be a non-integer
multiply('',4);
//TypeError: Argument cannot be a non-integer
- allArgsValid
, . , -. - , . . : , .
multiply
, . - allArgsValid
, , , . multiply
. , .
//ordinary add function
let add = function(a,b){
return a+b;
}
//decorated add function that only accepts the required number of params and only integers
add = allArgsValid(add);
add(6, 8);
//14
add(3, null);
//TypeError: Argument cannot be a non-integer
add('',4);
//TypeError: Argument cannot be a non-integer
: , TC39
JavaScript . 2- .
JavaScript — . — , .
, — . ? .
, .
function log(fn) {
return function() {
console.log("Execution of " + fn.name);
console.time("fn");
let val = fn();
console.timeEnd("fn");
return val;
}
}
class Book {
constructor(name, ISBN) {
this.name = name;
this.ISBN = ISBN;
}
getBook() {
return `[${this.name}][${this.ISBN}]`;
}
}
let obj = new Book("HP", "1245-533552");
let getBook = log(obj.getBook);
console.log(getBook());
//TypeError: Cannot read property 'name' of undefined
, getBook
, - log
. obj.getBook
. this
, Book
. TypeError
.
, Book
getBook
.
function log(classObj, fn) {
return function() {
console.log("Execution of " + fn.name);
console.time("fn");
let val = fn.call(classObj);
console.timeEnd("fn");
return val;
}
}
class Book {
constructor(name, ISBN) {
this.name = name;
this.ISBN = ISBN;
}
getBook() {
return `[${this.name}][${this.ISBN}]`;
}
}
let obj = new Book("HP", "1245-533552");
let getBook = log(obj, obj.getBook);
console.log(getBook());
//[HP][1245-533552]
Book
- log
, obj.getBook
, this
.
, . , .
.
Babel. JSFiddle
— , . , : .
@. - log
:
@log
- . - , . target
, .
target
, . , . .
, Book
, .
function log(target) {
return function(...args) {
console.log("Constructor called");
return new target(...args);
};
}
@log
class Book {
constructor(name, ISBN) {
this.name = name;
this.ISBN = ISBN;
}
getBook() {
return `[${this.name}][${this.ISBN}]`;
}
}
let obj = new Book("HP", "1245-533552");
//Constructor Called
console.log(obj.getBook());
//HP][1245-533552]
, log
target
. log
, target
, Book
. target
target.prototype.property.
, -, :
function logWithParams(...params) {
return function(target) {
return function(...args) {
console.table(params);
return new target(...args);
}
}
}
@log
@logWithParams('param1', 'param2')
class Book {
//Class implementation as before
}
let obj = new Book("HP", "1245-533552");
//Constructor called
//Params will be consoled as a table
console.log(obj.getBook());
//[HP][1245-533552]
, , @
. , , .
, , . , :
descriptor. 4 :
configurable
— , , ;
enumerable
— , , ;
value
— . ;
writable
— , , .
Book
.
//readonly decorator function
function readOnly(target, name, descriptor) {
descriptor.writable = false;
return descriptor;
}
class Book {
//Implementation here
@readOnly
getBook() {
return `[${this.name}][${this.ISBN}]`;
}
}
let obj = new Book("HP", "1245-533552");
obj.getBook = "Hello";
console.log(obj.getBook());
//[HP][1245-533552]
- readOnly
, getBook
Book
. writable
false
. true
.
writable
, getBook
, , :
obj.getBook = "Hello";
console.log(obj.getBook);
//Hello
. TypeScript , JavaScript 3- .
-, , , . . , value
. initializer
. , initializer
. initializer
.
(undefined
), writable
.
. Book
.
function upperCase(target, name, descriptor) {
if (descriptor.initializer && descriptor.initializer()) {
let val = descriptor.initializer();
descriptor.initializer = function() {
return val.toUpperCase();
}
}
}
class Book {
@upperCase
id = "az092b";
getId() {
return `${this.id}`;
}
//other implementation here
}
let obj = new Book("HP", "1245-533552");
console.log(obj.getId());
//AZ092B
id . - upperCase
initializer
, , ( undefined
). , « » (. .: . truthy — , true
Boolean
), . getId
. , .
. , .
Angular
TypeScript Angular, Angular, @Component
, @NgModule
, @Injectable
, @Pipe
. . .
MobX
MobX 6- . @observable
, @computed
@action
. MobX , . :
« ES, . , ».
Core Decorators
JavaScript, . 0, , 3- .
, @readonly
, @time
, @deprecate
. .
Redux React
Redux React connect
, React Redux. connect
.
//Before decorator
class MyApp extends React.Component {
// ...define your main app here
}
export default connect(mapStateToProps, mapDispatchToProps)(MyApp);
//After decorator
@connect(mapStateToProps, mapDispatchToProps)
export default class MyApp extends React.Component {
// ...define your main app here
}
connect
, Redux . , 2- , , .
— , . .
, , !
"JavaScript Developer. Professional".
" telegram Node.js".