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

[Javascript] Decorators in JavaScript的更多相关文章

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

    1.函数调用的四种方式 第三种:构造函数调用 如果构造函数调用在圆括号内包含一组实参列表,先计算这些实参表达式,然后传入函数内.这和函数调用和方法调用是一致的.但如果构造函数没有形参,JavaScri ...

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

    1.函数命名规范 函数命名通常以动词为前缀的词组.通常第一个字符小写.当包含多个单词时,一种约定是将单词以下划线分割,就像"like_Zqz()". 还有一种就是"lik ...

  3. javascript笔记:javascript的关键所在---作用域链

    javascript里的作用域是理解javascript语言的关键所在,正确使用作用域原理才能写出高效的javascript代码,很多javascript技巧也是围绕作用域进行的,今天我要总结一下关于 ...

  4. JavaScript强化教程——JavaScript 总结

    本教程中我们向您讲授了如何向 html 页面添加 JavaScript,使得网站的动态性和交互性更强. 你已经学习了如何创建对事件的响应,验证表单,以及如何根据不同的情况运行不同的脚本. 你也学到了如 ...

  5. JavaScript学习13 JavaScript中的继承

    JavaScript学习13 JavaScript中的继承 继承第一种方式:对象冒充 <script type="text/javascript"> //继承第一种方式 ...

  6. Javascript学习2 - Javascript中的表达式和运算符

    原文:Javascript学习2 - Javascript中的表达式和运算符 Javascript中的运算符与C/C++中的运算符相似,但有几处不同的地方,相对于C/C++,也增加了几个不同的运算符, ...

  7. Javascript学习1 - Javascript中的类型对象

    原文:Javascript学习1 - Javascript中的类型对象 1.1关于Numbers对象. 常用的方法:number.toString() 不用具体介绍,把数字转换为字符串,相应的还有一个 ...

  8. 第一百二十九节,JavaScript,理解JavaScript库

    JavaScript,理解JavaScript库 学习要点: 1.项目介绍 2.理解JavaScript库 3.创建基础库 从本章,我们来用之前的基础知识来写一个项目,用以巩固之前所学.那么,每个项目 ...

  9. 使用Javascript/jQuery将javascript对象转换为json格式数据 - 海涛的CSDN博客 - 博客频道 - CSDN.NET

    body{ font-family: "Microsoft YaHei UI","Microsoft YaHei",SimSun,"Segoe UI& ...

随机推荐

  1. iPad应用开发者的建议

    原文摘自Smashing Magazine<A Dad’s Plea To Developers of iPad Apps For Children> 我花了很长时间为孩子购买和测试iPa ...

  2. Zabbix3.0 自动微信报障

    本来研究了一段时间短信报障的,但是短信报障需要手机运营商的设备支持,就没有继续下去. 正好发现微信公众号可以报障,完全可以代替短信报警的功能. 首先你需要一个微信公众号,实名认不认证没关系. http ...

  3. 【书海】《Head First Java》 ——读后总结

    <Head First Java> 中文版 (第二版) IT`huhui前言录 <Head First Java>这本书我不算特别细的看了一遍.认为十分适合初学者,甚至是没接触 ...

  4. 写在Python前

    Python是用C编写的一种解释型语言,和shell一样,变量可以直接使用,而且就像C中的宏替换,但是Python同样支持进行底层的调用,可以很容易的和各种语言进行融合,俗称"胶水语言&qu ...

  5. 【Android开发】 第一课 环境搭建教程

    Windows 开发环境部署: Android Studio 中文社区:http://www.android-studio.org/ 本教程将分为五个步骤来完成Android开发环境的部署. 第一步: ...

  6. WEB项目后端跨域请求

    using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net ...

  7. ibatis + log4net 配置注意事项

    一 在web.config或app.config中配置 <configuration> <configSections> <sectionGroup name=" ...

  8. Linux系列笔记 - vim相关记录

    一.常用到的vim命令 这里只简单记录常用到的命令,后面会有自己记录的命令,但有些可能不常用. 常规模式: gg 跳到文件头 shift+g 跳到文件尾 行数+gg 跳到指定行 如:123gg 跳到1 ...

  9. java包装类的作用

    转载自http://zhidao.baidu.com/question/2052192149152534987.html 第一,基本数据类型之间的相互转换不是都可以制动转换的,而你强制转换又会出问题, ...

  10. android-sdks/build-tools/17.0.0/aapt: error while loading shared libraries: libz.so.1: cannot open shared object file: No such file or directory

    fedora 23:dnf install zlib.i686 libstdc++.i686