美文网首页
es6中装饰器的实现原理

es6中装饰器的实现原理

作者: Small_Song | 来源:发表于2021-02-16 09:52 被阅读0次

基于Node的web服务器开发中使用decorator对请求进行权限校验和数据格式的处理是一个看起来比较漂亮的写法,这里正好整理一下对javascript中的decorator的理解。

decorator的概念在其他语言中早有存在,在javascript中目前(2017/09/17)还处于stage 2阶段,基本确定会进入正式的ECMA规范了。但是目前还不能直接使用,只能使用babel来进行语法的转换。

官方的说法是:

Decorators make it possible to annotate and modify classes and properties at design time.

大概的意思就是在运行时改变类或者类的属性。

正文

首先看下装饰器常见的两种使用:

  1. 装饰一个类的属性。
function readonly(target, name, descriptor) {    
  discriptor.writable = false;    
  return discriptor;
}
class Cat {    
  @readonly    
  say() {        
      console.log("meow ~");    
  }
}
var kitty = new Cat();
kitty.say = function() {    
  console.log("woof !");
}
kitty.say()    // meow ~复制代码
  1. 装饰一个类。
function isAnimal(target) {    
  target.isAnimal = true;   
  return target;
}
@isAnimalclass 
Cat {    
  ...
}
console.log(Cat.isAnimal);    // true复制代码

装饰一个类的属性

ES6中的类实际上就是一个语法糖,本质上是构造函数,类的属性的定义使用的是 Object.defineProperty() 用一个简单的栗子来理解如下:

class Cat {    
  say() {        
    console.log("meow ~");    
  }
} 
function Cat() {}
Object.defineProperty(
  Cat.prototype, 
  "say", 
  {    
    value: function() { 
      console.log("meow ~"); 
    },    
  enumerable: false,    
  configurable: true,    
  writable: true
});

细心的小伙伴已经发现了

Object.defineProperty(obj, prop, descriptor)复制代码

接收的参数和作用于类的属性的时候装饰器函数的接收的参数很像。

可以知道作用于类的属性的时候的装饰器函数接收的参数就是上述ES6中的类定义属性时候使用Object.defineProperty时接收的参数,一模一样...

本质上也就是说装饰器在作用于类的属性的时候,实际上是通过 Object.defineProperty 来对原有的descriptor进行封装:

descriptor:

  • configurable控制是不是能删、能修改descriptor本身。
  • writable控制是不是能修改值。
  • enumerable控制是不是能枚举出属性。
  • value控制对应的值,方法只是一个value是函数的属性。
  • get和set控制访问的读和写逻辑。

通过处理descriptor可以改变原有属性。 被装饰的属性的定义在实际上执行的是以下的代码:

let descriptor = {    
  value: function() {        
    console.log("meow ~");    
  },    
  enumerable: false,    
  configurable: true,   
  writable: true};
  descriptor = readonly(Cat.prototype, "say", descriptor) || descriptor;
  Object.defineProperty(Cat.prototype, "say", descriptor);

也就是说,上面的那个@readonly其实就是

descriptor = readonly(Cat.prototype, "say", descriptor) || descriptor;复制代码

的语法糖,要注意的是,装饰器执行的时间是在属性定义的时候,也就是被装饰的属性在定义后就是已经被装饰器处理过的不一样的属性了。

装饰一个类

装饰一个类的时候类本身本质上是一个函数,没有descriptor,target是这个函数本身。

function isAnimal(target) {    
  target.isAnimal = true;   
  return target;
}
@isAnimalclass 
Cat {   
 ...
}
console.log(Cat.isAnimal);

也就是说,上面的@isAnimal其实就是做了下面这件事

Cat = isAnimal(function Cat() { ... });复制代码

在了解了两种情况下装饰器本质上做了什么之后,顺带可以看出,装饰器函数执行的时间:

function log(message) {    
  return function() {        
  console.log(message);    
  }
}
console.log('before class');
@log('class Bar')
class Bar {    
  @log('class method bar');    
  bar() {}    
  @log('class getter alice');    
  get alice() {}    
  @log('class property bob');    
  bob = 1;
}
console.log('after class');
let bar = {    
  @log('object method bar')    
  bar() {}
};

输出结果:

before class
class method bar
class getter alice
class property bob
class Bar
after class
object method bar

可以看出装饰器在定义时就执行了,也就对应着官方的那句话:

Decorators make it possible to annotate and modify classes and properties at design time.

在类和类的属性定义的时候就对它们进行了"装饰"。

以上大致的说了下javascript的装饰器的原理和使用,但是还有一些细节有待进一步的深入。

相关文章

  • [Decorator] 学习

    # Javascript 中的装饰器 # ES6 系列之我们来聊聊装饰器

  • es6中装饰器的实现原理

    基于Node的web服务器开发中使用decorator对请求进行权限校验和数据格式的处理是一个看起来比较漂亮的写法...

  • 2018-07-12(装饰器、迭代器、生成器)

    装饰器、迭代器、生成器 1、装饰器: 装饰器实现原理有两种,一种通过类,主要是通过__call__ 还有一种实现的...

  • TypeScript 装饰器

    TypeScript 与 ES6 的装饰器? ES6 的装饰器是一种函数,写成@ + 函数名。它可以放在类和类方法...

  • 装饰器

    """@装饰器- 普通装饰器- 带参数的装饰器- 通用装饰器- 装饰器装饰类- 内置装饰器- 缓存装饰器- 类实现...

  • Python 高级编程系列(二)

    Python 装饰器常见用法 装饰器与spring 中的AOP类似 通过装饰器可以实现面向切面的注入 一:缓存 ...

  • python3基础---详解装饰器

    1、装饰器原理 2、装饰器语法 3、装饰器执行的时间 装饰器在Python解释器执行的时候,就会进行自动装饰,并不...

  • 谈谈装饰器的实现原理

    关于我一个有思想的程序猿,终身学习实践者,目前在一个创业团队任team lead,技术栈涉及Android、Pyt...

  • 你需要知道的面试高频题-python装饰器

    面试高频题 面试官通常会问: 1. python 装饰器的作用是什么? 2. 装饰器的原理与实现? 考点分析 是否...

  • 11.装饰器(注解)、深浅拷贝

    一、装饰器 1). 装饰器概述 装饰器:Python中的代理模式的实现。 对其他函数进行增强。 原则:不修改被修饰...

网友评论

      本文标题:es6中装饰器的实现原理

      本文链接:https://www.haomeiwen.com/subject/mksexltx.html