• [Javascript] Decorators in JavaScript


    First, what is 'High Order function', basic just a function, inside the function return another fuction.

    // High order fucntion
    
    function fn() {
      return function(){
        
      }
    }

    For example:

    function compose(a, b) {
      return function(c){
        return a(b(c));
      }
    }
    
    function addTwo(val){
      return val + 2;
    }
    
    function tiemsTwo(val){
      return val * 2;
    }
    
    const val = compose(addTwo, tiemsTwo)(50);
    console.info(val); // 102

    Decorators is a subset of high order fucntion:

    function fluent(fn){
      return function(...args){
        fn.apply(this, args);
        return this;
      }
    }
    
    function Person(){}
    
    Person.prototype.setName = fluent(function(firstName, lastName){
      this.firstName = firstName;
      this.lastName = lastName;
    })
    
    Person.prototype.getName = fluent(function(){
      console.log(this.firstName + ' ' + this.lastName);
    })
    
    var p = new Person();
    
    console.log( p.setName('John', 'Kent').getName());

    In this code, fluent actually decorate Person class, make it chainable.

    But In ES6:

    class Person {
      setName(f, l) {
        this.firstName = f;
        this.lastName = l;
      }
      
      getName() {
        console.log(this.firstName, this.lastName);
      }
    }

    We have no way to wrap setName and getName fucntion in fluent(). So that's way decorator comes in.

    To use decorator to descorate a function in class:

    function decorate(target, keys, descriptor){
      var fn = descriptor.value;
      
      // Overwrite the value, which in this case is function
      descriptor.value = function(...args){
        fn.apply(target, args);
        return target;
      }
    }
    
    class Person {
      
      @decorate
      setName(firstName, lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
      }
      
      @decorate
      getName(){
        console.log(this.firstName, this.lastName);
      }
    }
    
    const p = new Person();
    console.log(p.setName("Wan", "Zhentian").getName());

    And it would be nice to reuse the fluent function:

    function fluent(fn){
      return function(...args){
        fn.apply(this, args);
        return this;
      }
    }

    So we can do:

    function fluent(fn){
      return function(...args){
        fn.apply(this, args);
        return this;
      }
    }
    
    
    function decorateWith(fn){
      return (target, keys, descriptor) => {
        // fn here refers to setName or getName
        // fn should be call with in target context, which means Person{}
        // the second argument in call() is function to be passed into fluent() function
    descriptor.value = fn.call(target, descriptor.value); } } class Person { @decorateWith(fluent) setName(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; } @decorateWith(fluent) getName(){ console.log(this.firstName, this.lastName); } } const p = new Person(); console.log(p.setName("Wan", "Zhentian").getName());

    [Note]: call(context, arguement, arguement, ....); here arguement is sinlge value

    apply(context, arguements): here arguements is array

  • 相关阅读:
    关于正无穷大取值小记
    Ubuntu16.04的图形化界面无法启动问题
    腾讯地图 API 调用入门
    背包九讲PDF
    剑指offer 题解记录
    C++ 各类型转换及关键字
    简易web服务器
    树 总结
    排序算法总结
    C++进阶知识整理
  • 原文地址:https://www.cnblogs.com/Answer1215/p/5582623.html
Copyright © 2020-2023  润新知