关于AOP装饰函数中的this
在学习关于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的更多相关文章
- Python-装饰器中保留被装饰函数元数据
函数的元数据包括哪些呢? 1. 函数名 .__name__ 2. 函数注释 .__doc__ ... 那,如何保留被装饰函数元数据,通过wraps装饰器保留被装饰函数的元数据 import time ...
- Spring AOP在函数接口调用性能分析及其日志处理方面的应用
面向切面编程可以实现在不修改原来代码的情况下,增加我们所需的业务处理逻辑,比如:添加日志.本文AOP实例是基于Aspect Around注解实现的,我们需要在调用API函数的时候,统计函数调用的具体信 ...
- Python 装饰器装饰类中的方法
title: Python 装饰器装饰类中的方法 comments: true date: 2017-04-17 20:44:31 tags: ['Python', 'Decorate'] categ ...
- python_如何修改装饰器中参数?
案例: 为分析程序内哪些函数执行时间开销较大,我们需定义一个带timeout参数的装饰器 需求: 统计被装饰函数的运行时间 时间大于timeout时,将此次函数调用记录到log日志中 运行时可以修改t ...
- Python装饰函数
from time import ctime, sleep def tsfunc(func): def wrappedFunc(): print('[%s] %s() classed' % (ctim ...
- python函数中闭包的概念说明
函数中闭包的概念说明 闭包: 内层函数对外层函数非全局变量的引用,就叫做闭包 判断闭包方法 ._closure_ : 执行后返回有效信息就是闭包,返回none就不是闭包 举例1: 是闭包 def wr ...
- python函数中的参数(关键字参数,默认参数,位置参数,不定长参数)
默认参数:定义函数的时候给定变量一个默认值. def num(age=1): 位置参数:调用函数的时候根据定义函数时的形参位置和实参位置进行引用. 关键字参数:如果定义的函数中含有关键字参数,调用函数 ...
- python 装饰函数2
#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Created on Tue May 5 21:40:49 2020 ...
- 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. ...
随机推荐
- 学号:201521123116 《java程序设计》第二周学习总结
1. 本章学习总结 一:学习了string的类型,string的对象是不可变的,创建之后不能再修改 二:SET PATH/CLASSPATH和-cp的用法. 三:学习了Java API 文档的使用方法 ...
- 201521123110《Java程序设计》第1周学习总结
1.第一周学习总结 `本周开始了对java的初次学习接触,Java是一门新的编程语言不同于C,由于有了c的基础,对于Java的理解和学习也相对从前学C更容易些. 也学习了Java的诞生发展以及运用包括 ...
- 201521123104 《Java程序设计》第14周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多数据库相关内容. 2. 书面作业 1. MySQL数据库基本操作 1.1 建立数据库,将自己的姓名.学号作为一条记录插入.(截图, ...
- 201521123109《java程序设计》第十周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常与多线程相关内容. 2. 书面作业 本次PTA作业题集异常.多线程 1. finally 题目4-2 1.1 截图你的提交结果( ...
- [01] Java语言的基本认识
0.写在前面的话 我们都知道在计算机的底层,它是识别二进制的,也就是说,计算机只能认识0和1.这主要是因为电路的逻辑只有两种状态,所以只需要0和1两个数字就可以表示低电平和高电平.而计算机是由数不清的 ...
- Activiti-06-.事件
Events 事件 1, 事件用于对发生在流程生命周期的事情进行建模.事件总是被形象成一个圆圈.在BPMN 2.0 中,存在两种主要的事件类型:捕获事件和抛出事件. 捕获:流程执行到该事件时,会等待 ...
- 对Java的初识
什么是计算机程序: 为了让计算机执行某些操作或解决某个问题而编写的一系列有序指令的集合.(简单来说就是记算机为完成某些功能生产的一系列有序指令集合); Java的来历: Java的初期开发早在 ...
- GCD之信号量机制二
在前面GCD之信号量机制一中介绍了通过信号量设置并行最大线程数,依此信号量还可以防止多线程访问公有变量时数据有误,下面的代码能说明. 1.下面是不采用信号量修改公有变量的值 1 2 3 4 5 6 7 ...
- php调用webservice接口
项目中使用到了调用三方厂商webService接口.他的接口类似为http://haha.cn:86/BaseInfoService.svc?wsdl,在这里我注意到了"wsdl" ...
- oracle pl/sql 分页
一.无返回值的存储过程 古人云:欲速则不达,为了让大家伙比较容易接受分页过程编写,我还是从简单到复杂,循序渐进的给大家讲解.首先是掌握最简单的存储过程,无返回值的存储过程. 案例:现有一张表book, ...