[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

时间: 2024-10-23 22:15:15

[Javascript] Decorators in JavaScript的相关文章

轻松学习JavaScript五:JavaScript的变量和数据类型

对于一们编程语言,肯定包含变量和数据类型.今天我们就来看看JavaScript脚本语言的变量和数据类型.相对 于其他的Java,C++等高级程序语言,JavaScript显得很简单. 一变量 JavaScript的变量是松散类型的,所谓松散就是用来保存任何类型的数据.变量是存储信息的容器.定义变量时 要使用var操作符(var是关键字),后面跟一个变量名(变量名是标识符).变量也就是初始化后可以再次改变的量. 那么我们来看看实例: <span style="font-size:18px;&

JavaScript权威设计--JavaScript函数(简要学习笔记十)

1.函数命名规范 函数命名通常以动词为前缀的词组.通常第一个字符小写.当包含多个单词时,一种约定是将单词以下划线分割,就像"like_Zqz()". 还有一种就是"likeZqz()".有些些函数是用作内部用的或者为私有函数通常以一条下划线为前缀,就像"_zqzName()". 2.以表达式方式定义的函数 如: var zqz=function (){ return "zhaoqize"; } 在使用的时候必须把它赋值给一个变

javascript篇:javascript对象——Math

Math对象用于执行数学任务,无需创建它的实例: var mathPI = Math.PI; var myVal = Math.sqrt(4); Math对象的属性 E:返回算术常量e,约等于2.718 LN2:返回2的自然对数,约等于0.693 LN10:返回10的自然对数,约等于2.302 LOG2E:返回以2为底的e的对数,约等于1.414 LOG10E:返回以10为底的e的对数,约等于0.434 PI:返回圆周率,约等于3.14159 SQRT1_2:返回2的平方根的倒数,约等于0.70

Unit04: JavaScript 概述 、 JavaScript 基础语法 、 流程控制

Unit04: JavaScript 概述 . JavaScript 基础语法 . 流程控制 my.js function f3() { alert("唐胜伟"); } demo1.html  演示点击按钮,弹出提示框 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> <

JavaScript学习13 JavaScript中的继承

JavaScript学习13 JavaScript中的继承 继承第一种方式:对象冒充 <script type="text/javascript"> //继承第一种方式:对象冒充 function Parent(username) //父类对象 { this.username = username; //下面的代码最关键的部分就是将子对象的this传递给了父对象 this.sayHello = function() { alert(this.username); } } f

javascript基础——初识javascript

每一门语言的学习都是从HelloWorld开始的,我今天也遵循这个原则吧!先上一段代码,认识一下javascript <html><head><title>初识javascript</title><script language="javascript" type="text/javascript"><!--alert("Hello World Wide Web!")//-->

轻松学习JavaScript十一:JavaScript基本类型(包含类型转换)和引用类型

一值的类型 早在介绍JS的数据类型的时候就提到过基本类型和引用类型,不过在说两种类型之前,我们先来了解一下变量的 值的类型.在ECMAScript中,变量可以存在两种类型的值,即原始值和引用值. (1)原始值 存储在栈中的简单数据段,也就是说,它们的值直接存储在变量访问的位置. (2)引用值 存储在堆中的对象,也就是说,存储在变量处的值是一个指针,指向存储对象的内存处. 为变量赋值时,ECMAScript的解释程序必须判断该值是原始类型,还是引用类型.要实现这一点,解释程序则需 尝试判断该值是否

javascript篇:javascript对象——Date

Date对象是javascript的内置对象,用于处理日期和时间,使用前必须定义: var myDate = new Date();//Date对象会自动初始化该对象,使其值为当前日期和时间. var myDate = new Date("June 15, 1990 00:00:00"); var myDate = new Date(milsec);//参数为距离1970/1/1午夜的毫秒数 以上方式定义myDate 是本地时间,而不是UTC时间. Date对象的属性: constru

javaScript Code 用javascript确定每月第二个星期五

废话少说只就上Code: 说明:getDay()方法获取星期(这里的星期是从0到6).参见:http://www.w3school.com.cn/js/js_obj_date.asp 中的getDay(). 代码有不足之处希望得到指正. var SecondFriday = { getSecondFriday: function () { var flag = 0; //(1) 获取当月月初时间,时间格式为:Sun Jun 01 2014 00:00:00 GMT+0800 (中国标准时间) v