关于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. ...
随机推荐
- 团队作业4——第一次项目冲刺(Alpha版本) Day6
首先和助教及老师表示抱歉,博客确实当时就写了,但是一直不算写好,因为这几天卡住了,预计实现的功能实现不了,进度跟不上,现在也在寻求解决方法. 1.站立式会议: 2. Leangoo任务分解图: 3.任 ...
- 201521123062《Java程序设计》第8周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. 1.2 选做:收集你认为有用的代码片段 for (int i = 0; i < list.size(); ...
- 学号:201521123116 《java程序设计》第八周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. 1.2 选做:收集你认为有用的代码片段 List<Entry<String,Integer> ...
- 201521123030 《Java程序设计》第7周学习总结
1. 本周学习总结 以你喜欢的方式(思维导图或其他)归纳总结集合相关内容. 2. 书面作业 1.ArrayList代码分析 1.1 解释ArrayList的contains源代码 public boo ...
- 201521123044 《Java程序设计》第2周作业-Java基本语法与类库
1. 本章学习总结 ·1.浮点型的不精确,不能简单的像C语言一样用float或者double来定义.在java中有更精确的BigDecimal类. 举例:BigDecimal bd1= new Big ...
- 201521123099 《Java程序设计》第9周学习总结
1. 本周学习总结 2. 书面作业 题目5-1 1.1 截图你的提交结果(出现学号) 1.2 自己以前编写的代码中经常出现什么异常.需要捕获吗(为什么)?应如何避免? 容易出现拼写错误还有数组越界的异 ...
- Struts2第十二篇【模型驱动】
什么是模型驱动 在Struts2中模型驱动就是用来封装数据的..完成数据的自动封装. 为什么要使用模型驱动? 我们之前就使用过Sturts2的数据自动封装功能,是用params拦截器完成的-既然有了p ...
- Python学习笔记013_正则表达式
Python中的正则表达式是通过 re 模块实现的. 通配符 . 表示除了换行以外的任何字符; 编写正则表达式时使用 r're' , r + 正则表达式内容 >>> impor ...
- Jupyter(Python)中无法使用Cache原理分析
前言 最近需要在Jupyter中写一个类库,其中有一个文件实现从数据库中读取空间数据并加载为Feature对象,Feature对象是cartopy封装的geomery列表,能够方便的用于作图等.因为有 ...
- 西邮linux兴趣小组2014纳新免试题(一)
[第一关] 题目 0101001001100001011100100010000100011010000001110000000011001111100100000111001100000000000 ...