在学习关于JavaScript的装饰者设计模式的过程中,发现其实现方式的关键在于this的使用。

  想象一个匿名函数(其实预定义的有名函数也可以,都存在引用),其中的this:

 // 我们先定义一个匿名函数的引用foo
var foo = function(){
console.log(`我是 ${this}`)}; //创建一个空的Object实例 var bar = {}; //很空 但是依然有其默认原型Object.prototype的方法和属性 //如果我们写出下列语句 bar.foo = foo; //这意味着把上面定义的匿名函 ”挂载“到实例bar的foo方法中 //
bar.foo() //我是 [object Object](bar)。这里其实调用了Object原型上的toString方法,下同。 foo() // 我是 [object global](node: global/ 浏览器: window)

  到这里,读者可能会疑惑,这个”挂载“的过程跟题目的AOP装饰函数有什么关系。

  在JS中,装饰模式的实现简单来说就是 将对象的某个原方法与其他的函数进行加工合并,从而输出一个”匿名函数“, 就像上面代码定义的匿名函数一样,将这个输出的”匿名函数“,”挂载到原对象的原方法上面“,就完成了在原方法前后产生附加动作的效果。

  我们给出AOP的基础实现代码,一步步的分析:

 //首先定义对象
//这个对象有属性score,以及方法main var bar = {
score : 60,
main: function(){ console.log("我的分数"+this.score);}
}; //突然,我想另外输出bar同学分数的平方根, 要求不过分吧
//可能你会想到,在bar同学中添加新的方法去输出平方根,或者定义一个新的函数去处理bar同学的分数。 //接下来,我们利用AOP来实现这个方法 Function.prototype.after= function(fn){
var _self = this;
return function(){
var result = _self.apply(this,arguments);
fn.apply(this,arguments);
return result; };
}; //输出平方根的函数
function sqrt(){
console.log("我的分数的平方根"+Math.sqrt(this.score));}
//挂载到main上 bar.main = bar.main.after(sqrt); //输出新的合成匿名函数
bar.main();//我的分数60
// 我的分数的平方根7.745966692414834

  看到14-20行的代码中的this,其实我一开始有点懵,第一个this指的是 Function实例——即bar.main,而返回的匿名函数中的this是指其挂载的对象,这里是挂载的是bar,如果不挂载的话,这个this就指向运行环境的顶层对象或者null,这是需要关注的地方,换句话说,如果没有那两句apply语句,那么合成匿名函数的这些函数集合中的this可能会丢失,而指向顶层对象或者null。

  所以在装饰者模式中,this的指向与是否挂载息息相关,进一步的说,在代码的某个地方使用this,无论是函数声明的语句,还是运行上下文中的语句,及时保存this的指向和挂载正确的对象 都是十分必要的!

关于AOP装饰函数中的this的更多相关文章

  1. Python-装饰器中保留被装饰函数元数据

     函数的元数据包括哪些呢? 1. 函数名 .__name__ 2. 函数注释 .__doc__ ... 那,如何保留被装饰函数元数据,通过wraps装饰器保留被装饰函数的元数据 import time ...

  2. Spring AOP在函数接口调用性能分析及其日志处理方面的应用

    面向切面编程可以实现在不修改原来代码的情况下,增加我们所需的业务处理逻辑,比如:添加日志.本文AOP实例是基于Aspect Around注解实现的,我们需要在调用API函数的时候,统计函数调用的具体信 ...

  3. Python 装饰器装饰类中的方法

    title: Python 装饰器装饰类中的方法 comments: true date: 2017-04-17 20:44:31 tags: ['Python', 'Decorate'] categ ...

  4. python_如何修改装饰器中参数?

    案例: 为分析程序内哪些函数执行时间开销较大,我们需定义一个带timeout参数的装饰器 需求: 统计被装饰函数的运行时间 时间大于timeout时,将此次函数调用记录到log日志中 运行时可以修改t ...

  5. Python装饰函数

    from time import ctime, sleep def tsfunc(func): def wrappedFunc(): print('[%s] %s() classed' % (ctim ...

  6. python函数中闭包的概念说明

    函数中闭包的概念说明 闭包: 内层函数对外层函数非全局变量的引用,就叫做闭包 判断闭包方法 ._closure_ : 执行后返回有效信息就是闭包,返回none就不是闭包 举例1: 是闭包 def wr ...

  7. python函数中的参数(关键字参数,默认参数,位置参数,不定长参数)

    默认参数:定义函数的时候给定变量一个默认值. def num(age=1): 位置参数:调用函数的时候根据定义函数时的形参位置和实参位置进行引用. 关键字参数:如果定义的函数中含有关键字参数,调用函数 ...

  8. python 装饰函数2

    #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Created on Tue May 5 21:40:49 2020 ...

  9. JS中bind、call和apply的作用以及在TS装饰器中的用法

    目录 1,前言 1,call 1.1,例子 1.2,直接调用 1.3,将this指向另一个对象 1.4,传递参数 2,apply 2.1,例子 2.2,直接调用 2.3,将this指向另一个对象 2. ...

随机推荐

  1. week2-结对编程【网页实现四则运算】

    题目描述: 不知道大家是否尝试过这样一种开发模式:你有一个伙伴,你们坐在一起,并肩作战,面对着同一台显示器,使用着同一键盘,同一个鼠标,你们一起思考,一起分析,一起编程?这次,就让我们来体验一下结对编 ...

  2. 在配置github中遇到的一些问题

    这次在配置github时,我出现了问题,就是在我装好Git以后,我打开Git Bash,输入了这句代码:$ ssh-keygen -t rsa -C "your_email@youremai ...

  3. 201521123121 《Java程序设计》第4周学习总结

    1. 本周学习总结 1.1 尝试使用思维导图总结有关继承的知识点. 1.2 使用常规方法总结其他上课内容. 对象的封装:将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现 ...

  4. 201521123088 《Java程序设计》第1周学习总结

    第1周学习总结 1.本周学习总结本周我们正式开始了对一门新的编程语言java的学习.Java是一门面向对象编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承.指针等概念,因此J ...

  5. 201521123024 《Java程序设计》第1周学习总结

    一.本周章学习总结 1.Java的版本迁移 2.运用eclipse和notepad++编写Java 3.对JDK,JRE,JVM有初步的了解 二.书面作业 1.为什么java程序可以跨平台运行?执行j ...

  6. Python[小甲鱼-002用Python设计第一个游戏]

    –Code——————————————————————- print("----------第一个小游戏----------") temp = input("猜一下我现在 ...

  7. Java I/O 从0到1 - 第Ⅰ滴血 File

    前言 File 类的介绍主要会依据<Java 编程思想>以及官网API .相信大家在日常工作中,肯定会遇到文件流的读取等操作,但是在搜索过程中,并没有找到一个介绍的很简洁明了的文章.因此, ...

  8. 移动商城第三篇【搭建Mybatis和Spring环境、编写Dao、Service在Core模块】

    Mybatis和Spring环境搭建 由于我们的所编写的dao层.service代码可能前台和后台都需要用到的,因此我们把环境搭建在core模块中 逆向工程 首先,我们要做的就是品牌管理,我们首先来看 ...

  9. Log4j.properties属性文件

    log4j.properties文件属性介绍log4j.rootLogger = [ level ] , appenderName1, appenderName2, …#level : 设定日志记录的 ...

  10. python import xxx 与 from xxx import xx 模块引入的区别

    有如下脚本script1.py: A='aaaa'B='bbbb'C='cccc'print A,B,C 1.命令行交互模式下使用import 导入方式1: >>>import sc ...