مصممي جافا سكريبت من البداية

ندعو الطلاب المستقبليين لدورة "JavaScript Developer. Professional" للاشتراك في درس مفتوح حول موضوع "إنشاء روبوت برقية تفاعلي على Node.js" .



والآن نشارك الترجمة التقليدية للمواد المفيدة.






فهم وظائف الديكور

ما هو المصمم؟

المصمم هو وسيلة تسمح لك بلف وظيفة بأخرى وتوسيع إمكانياتها. يمكنك "تزيين" الكود الموجود عن طريق تغليفه في كود آخر. هذه الحيلة مألوفة لأي شخص على دراية بتكوين الوظيفة أو وظائف الترتيب الأعلى.





الديكور ليس جديدا. يتم استخدامها في لغات أخرى أيضًا ، مثل Python ، وحتى البرمجة الوظيفية في JavaScript. لكننا سنتحدث عن هذا لاحقًا.





لماذا نحتاج الديكور؟

إنها تسمح لك بكتابة كود أنظف ، والالتزام بمفهوم التكوين ، وتوسيع القدرة المطورة مرة واحدة إلى وظائف وفئات متعددة. باستخدام أدوات الديكور ، يمكنك كتابة التعليمات البرمجية التي يسهل تصحيحها وصيانتها.





, , , . , .





2- , .





. Bit (Github). .





, .





Bit  Node, TypeScript, React, Vue, Angular JS.





أمثلة على مكونات React القابلة لإعادة الاستخدام على Bit.dev
React- Bit.dev

?

 — . , -. -, . , .





?

.





 — . , 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]
      
      



, , @



. , , .





, , . , :





  • target



     — , , ;





  • name



     — , ;





  • descriptor



     — , , .   .





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
}
      
      



Felix Kling Stack Overflow .





connect



  , Redux . , 2- , , .





 — , . .





, , !






"JavaScript Developer. Professional".



" telegram Node.js".












All Articles