📜  什么是装饰器以及它们如何在 JavaScript 中使用?

📅  最后修改于: 2022-05-13 01:56:32.383000             🧑  作者: Mango

什么是装饰器以及它们如何在 JavaScript 中使用?

装饰器是用另一段代码包装一段代码或在 JavaScript 中对函数应用包装器的方式。装饰器是允许将行为添加到单个对象的设计模式,无论是静态的还是动态的,而不影响同一类中其他对象的行为。它们用于在不修改底层函数的情况下增强函数的函数。他们只是通过返回一个新函数来修改传递给它的函数或方法的行为。装饰器已经在Python和 C# 等语言中使用,现在它也用于 JavaScript。

  • 句法:
let variable=function(object) {
  object.property='characteristic';
}

// Use as decorator
@variable   
class GFG
{ }
console.log(GFG.property);
  • 示例:此示例使用较低版本的 JavaScript 实现装饰器的工作。在本例中,函数addprint函数作为参数。这里print函数作为装饰器工作。它有助于将“最佳”字符串连接到传递的字符串“GFG” 。这里我们使用“add”函数通过连接字符串来扩展和执行“print”函数。
Javascript


Javascript
let variable = function(target) {
  target.property = 'GFG is best';
}
 
// Decorator
@variable 
class GFG
{ }
  
// Print in the console
console.log(GFG.property);


Javascript
let variable = function(color) {
    return function (target) {
      target.property = color;
  }
};
  
// The value is passed in the decorator
@variable('GFG is Green')
class GFG
{ }
   
console.log(GFG.property);


Javascript
// Decorator function
function gfg(target, name, descriptor) {
  var fn = descriptor.value;
 
  // Checks if "descriptor.value"
  // is a function or not
  if (typeof fn == 'function') {
    descriptor.value = function(...args) {
  
      // Document.write(`parameters: ${args}`+"
");       console.log(`parameters: ${args}`);       var result = fn.apply(this, args);          // Document.write(`addition: ${result}`);          // Print the addition of passed arguments       console.log(`addition: ${result}`);                          return result;     }   }   return descriptor;  }         class geek {   @gfg   add(a, b) {     return a + b;   } }    var e = new geek(); e.add(100, 200);


Javascript
let readonly = function(target, key, descriptor) {
  descriptor.writable = false;
    
  return descriptor;
}
 
class car {
  constructor(color) {
      this.color = color;
  }
   
  // Decorator
  @readonly
  getColor() {
      return this.color;
  }
}
  
const rCar = new car('car is Black');
  
// When  descriptor.writable = false;
rCar.getColor = function() {
   
    // When  descriptor.writable = true;
    return 'car is not Black'
}
  
console.log(rCar.getColor());


Javascript
function log()
 
// Decorator function
{
  return function decorator()
    {
    // "arrow" function
    return (...args) =>
        {
      console.log(`Parameters : args`);
      return new Class(...args);
    };
  }
}
 
// Decorators
@log 
class gfg
{
  constructor(name, category) {}
}
 
const e = new gfg('geek', 'code');
 
// Arguments for Demo: args
console.log(e);


  • 输出:
GFG is Best

运行过程:要运行装饰器,它需要浏览器中的转译器支持,但目前没有浏览器支持这个。

  • Step1:我们使用BabelJS ,然后我们可以在浏览器上运行装饰器。在这里,我们将使用jsfiddle来运行代码。
  • 第二步:jsfiddle下选择Babel+JSX选项,否则程序将无法运行,只有 JavaScript 会显示错误@

下面的示例说明了 JavaScript 中的装饰器

  • 示例 1:

Javascript

let variable = function(target) {
  target.property = 'GFG is best';
}
 
// Decorator
@variable 
class GFG
{ }
  
// Print in the console
console.log(GFG.property);
  • 输出:
GFG is best
  • 示例 2:

Javascript

let variable = function(color) {
    return function (target) {
      target.property = color;
  }
};
  
// The value is passed in the decorator
@variable('GFG is Green')
class GFG
{ }
   
console.log(GFG.property);
  • 输出:
GFG is Green

为什么要使用装饰器?
我们可以使用装饰器来装饰代码,但是这种装饰很难应用,并且也很难将相同的技术应用于其他代码段,或者将一段代码与另一段代码包装在一起或在函数周围应用包装器是困难的。在 ES6 中,装饰器可以解决这些困难。装饰器允许以一种有效且易于理解的方式将一段代码与另一个函数或另一个代码包装起来。此外,装饰器为应用这些包装器提供了清晰的语法。不直接支持 JavaScript 装饰器,但将来可能会将装饰器支持添加到 javascript 中。

装饰器的类型:装饰器由将被装饰的项目的适当细节调用。装饰器实际上是返回另一个函数的函数。现在支持两种类型的装饰器:

  • 类成员装饰器
  • 班级成员

类成员装饰器:这些装饰器应用于类的单个成员。这个装饰器有属性、方法、getter、setter。这个装饰器接受 3 个参数:

  • target:成员所属的类。
  • name:类成员的名称。
  • 描述符:成员的描述,它是传递给Object.defineProperty的对象。

示例 1:在此示例中,我们传递了两个参数,这里装饰器函数检查描述符是否为函数,然后打印参数和它们的相加。函数add在这里使用另一个函数gfg进行修饰。

Javascript

// Decorator function
function gfg(target, name, descriptor) {
  var fn = descriptor.value;
 
  // Checks if "descriptor.value"
  // is a function or not
  if (typeof fn == 'function') {
    descriptor.value = function(...args) {
  
      // Document.write(`parameters: ${args}`+"
");       console.log(`parameters: ${args}`);       var result = fn.apply(this, args);          // Document.write(`addition: ${result}`);          // Print the addition of passed arguments       console.log(`addition: ${result}`);                          return result;     }   }   return descriptor;  }         class geek {   @gfg   add(a, b) {     return a + b;   } }    var e = new geek(); e.add(100, 200);
  • 输出:
parameters: 100, 200
addition: 300
  • 示例 2:

Javascript

let readonly = function(target, key, descriptor) {
  descriptor.writable = false;
    
  return descriptor;
}
 
class car {
  constructor(color) {
      this.color = color;
  }
   
  // Decorator
  @readonly
  getColor() {
      return this.color;
  }
}
  
const rCar = new car('car is Black');
  
// When  descriptor.writable = false;
rCar.getColor = function() {
   
    // When  descriptor.writable = true;
    return 'car is not Black'
}
  
console.log(rCar.getColor());
  • 输出:
car is Black

类成员:这些装饰器应用于整个类。这些函数是用一个要修饰的参数调用的。这个函数是一个构造函数。这些装饰器并不适用于类的每个实例,它只适用于构造函数。这些装饰器不如类成员装饰器有用。因为我们可以使用一个简单的函数来完成这些装饰器可以完成的所有事情。

  • 例子:

Javascript

function log()
 
// Decorator function
{
  return function decorator()
    {
    // "arrow" function
    return (...args) =>
        {
      console.log(`Parameters : args`);
      return new Class(...args);
    };
  }
}
 
// Decorators
@log 
class gfg
{
  constructor(name, category) {}
}
 
const e = new gfg('geek', 'code');
 
// Arguments for Demo: args
console.log(e);
  • 输出:
(...args) =>  
    {
      console.log(`Parameters : args`);
      return new Class(...args);
    }