koa2--delegates模块源码解读
delegates模块是由TJ大神写的,该模块的作用是将内部对象上的变量或函数委托到外部对象上。
然后我们就可以使用外部对象就能获取内部对象上的变量或函数。delegates委托方式有如下:
getter: 外部对象可以通过该方法访问内部对象的值。
setter:外部对象可以通过该方法设置内部对象的值。
access: 该方法包含getter和setter功能。
method: 该方法可以使外部对象直接调用内部对象的函数。
项目文件如下结构:
|----- 项目
| |-- delegates.js # 委托代理的js
| |-- index.js # 入口文件的js
1. getter (外部对象可以通过该方法访问内部对象的值。)
使用方法demo如下(index.js):
const delegates = require('./delegates'); const obj = {
xx: {
name: 'kongzhi',
age: 30,
test: function() {
console.log('xxxxxxx');
}
}
}; // 通过delegates将内部对象 xx 委托到外部对象obj上 var d = new delegates(obj, 'xx');
d.getter('name').getter('age').getter('test'); console.log(obj.name); // kongzhi
console.log(obj.age); //
obj.test(); // xxxxxxx
2. setter (外部对象可以通过该方法设置内部对象的值。)
使用方法的demo如下(代码在index.js内):
const delegates = require('./delegates'); const obj = {
xx: {
name: 'kongzhi',
age: 30,
test: function() {
console.log('xxxxxxx');
}
}
}; // 通过delegates将内部对象 xx 委托到外部对象obj上 var d = new delegates(obj, 'xx');
d.setter('name').setter('age').setter('test'); // 使用setter后,就可以在obj对象上直接修改变量或函数的值了
obj.name = '123456';
obj.age = '31';
obj.test = function() {
console.log('yyyy');
} /*
在外部对象obj修改完成后,我们再使用 外部对象[内部对象][变量]
这种方式获取值, 就可以看到值更新了
*/
console.log(obj.xx.name); //
console.log(obj.xx.age); //
obj.xx.test(); // yyyy
3. access (该方法包含getter和setter功能。)
使用方法的demo如下
const delegates = require('./delegates'); const obj = {
xx: {
name: 'kongzhi',
age: 30,
test: function() {
console.log('xxxxxxx');
}
}
}; // 通过delegates将内部对象 xx 委托到外部对象obj上 var d = new delegates(obj, 'xx');
d.access('name').access('age').access('test'); // access 该方法既有setter功能,又有getter功能 // 1. 直接使用外部对象 obj, 来访问内部对象中的属性
console.log(obj.name); // kongzhi
console.log(obj.age); //
obj.test(); // xxxxxxx // 2. 使用常规的方法获取对象的内部的属性
console.log(obj.xx.name); // kongzhi
console.log(obj.xx.age); //
obj.xx.test(); // xxxxxxx // 3. 修改内部对象的属性
obj.name = '2222';
console.log(obj.name); //
console.log(obj.xx.name); //
4. method (该方法可以使外部对象直接调用内部对象的函数。)
使用方法的demo如下:
const delegates = require('./delegates'); const obj = {
xx: {
name: 'kongzhi',
age: 30,
test: function() {
console.log('xxxxxxx');
}
}
}; // 通过delegates将内部对象 xx 委托到外部对象obj上 var d = new delegates(obj, 'xx');
d.method('test'); obj.test(); // xxxxxxx
5. fluent
该方法的作用是,如果该方法传了参数的话,那么它的含义是修改该变量的值,如果没有传入参数的话,那么
它的作用是获取该参数的值。
注意:只针对变量有用,如果是函数的话,不建议使用;
如下代码demo所示:
const delegates = require('./delegates'); const obj = {
xx: {
name: 'kongzhi',
age: 30,
test: function() {
console.log('xxxxxxx');
}
}
}; // 通过delegates将内部对象 xx 委托到外部对象obj上
var d = new delegates(obj, 'xx');
d.fluent('name').fluent('age'); // 无参数 获取该对象的值
console.log(obj.name()); // kongzhi
console.log(obj.age()); // // 有参数,就是修改对应的值
obj.name('11111')
obj.age(31) console.log(obj.xx.name); //
console.log(obj.xx.age); //
二:delegates模块源码如下:
/**
* Expose `Delegator`.
*/ module.exports = Delegator; /**
* Initialize a delegator.
*
* @param {Object} proto
* @param {String} target
* @api public
*/
/*
Delegator 函数接收二个参数,proto指是一个是外部对象,target指外部对象中的一个属性,也就是内部对象。
首先判断this是否是Delegator的实列,如果不是实列的话,就直接使用 new 实列化一下。
因此 const xx = Delegator(obj, 'xx') 或 const xx = new Delegator(obj, 'xx') 都是可以的。
this.proto = proto; 外部对象保存该实列this.proto 中。
this.target = target; 和proto一样。
this.methods = [];
this.getters = [];
this.setters = [];
this.fluents = [];
如上四个数组作用是 记录委托了哪些属性和函数。
*/
function Delegator(proto, target) {
if (!(this instanceof Delegator)) return new Delegator(proto, target);
this.proto = proto;
this.target = target;
this.methods = [];
this.getters = [];
this.setters = [];
this.fluents = [];
} /**
* Delegate method `name`.
*
* @param {String} name
* @return {Delegator} self
* @api public
*/
/*
method的作用是:该方法可以使外部对象直接调用内部对象的函数。如下demo:
const obj = {
xx: {
name: 'kongzhi',
age: 30,
test: function() {
console.log('xxxxxxx');
}
}
};
// 通过delegates将内部对象 xx 委托到外部对象obj上
var d = new delegates(obj, 'xx');
d.method('test'); obj.test(); // xxxxxxx 1. 首先我们调用 d.method('test'); 就把该test方法存入 this.methods数组中。
2. 该方法返回了一个函数
obj['test'] = function() {
return obj['xx']['test'].apply(obj['xx'], arguments);
}
3. 最后返回 this, 返回该实例化对象,目的是可以链式调用。
4. 因此就返回了第二步函数。因此当我们使用 obj.test() 的时候,就会自动调用该函数。然后
使用 apply方法自动执行 obj['xx']['test'].apply(obj['xx'], arguments);
*/
Delegator.prototype.method = function(name){
var proto = this.proto;
var target = this.target;
this.methods.push(name); proto[name] = function(){
return this[target][name].apply(this[target], arguments);
}; return this;
}; /**
* Delegator accessor `name`.
*
* @param {String} name
* @return {Delegator} self
* @api public
*/
/*
该方法的作用是包含 getter的作用,同时也包含setter的作用,如demo如下:
const obj = {
xx: {
name: 'kongzhi',
age: 30,
test: function() {
console.log('xxxxxxx');
}
}
}; // 通过delegates将内部对象 xx 委托到外部对象obj上 var d = new delegates(obj, 'xx');
d.access('name').access('age').access('test'); // access 该方法既有setter功能,又有getter功能 // 1. 直接使用外部对象 obj, 来访问内部对象中的属性
console.log(obj.name); // kongzhi
console.log(obj.age); // 30
obj.test(); // xxxxxxx // 2. 使用常规的方法获取对象的内部的属性
console.log(obj.xx.name); // kongzhi
console.log(obj.xx.age); // 30
obj.xx.test(); // xxxxxxx // 3. 修改内部对象的属性
obj.name = '2222';
console.log(obj.name); // 2222
console.log(obj.xx.name); // 2222
*/
Delegator.prototype.access = function(name){
return this.getter(name).setter(name);
}; /**
* Delegator getter `name`.
*
* @param {String} name
* @return {Delegator} self
* @api public
*/
/*
getter,该方法的作用是:外部对象可以通过该方法访问内部对象的值。比如如下demo
const obj = {
xx: {
name: 'kongzhi',
age: 30,
test: function() {
console.log('xxxxxxx');
}
}
}; // 通过delegates将内部对象 xx 委托到外部对象obj上
var d = new delegates(obj, 'xx');
d.getter('name').getter('age').getter('test'); console.log(obj.name); // kongzhi
console.log(obj.age); // 30
obj.test(); // xxxxxxx 1. 该方法接收一个参数 name, 该参数是一个字符串类型。
2. 把该参数name值保存到 this.getters数组中。然后我们使用 __defineGetter__ 监听对象属性值的变化。
想要理解 __defineGetter__ 作用,请看我这篇文章 (https://www.cnblogs.com/tugenhua0707/p/10324983.html#_labe1)
如果获取该对象值的话,就会自动调用 __defineGetter__ ,就能监听到,因此就返回 this[target][name]; 即使:
obj['xx']['name'];
*/
Delegator.prototype.getter = function(name){
var proto = this.proto;
var target = this.target;
this.getters.push(name); proto.__defineGetter__(name, function(){
return this[target][name];
}); return this;
}; /**
* Delegator setter `name`.
*
* @param {String} name
* @return {Delegator} self
* @api public
*/
/*
该方法的作用是:外部对象可以通过该方法设置内部对象的值。使用demo如下:
const obj = {
xx: {
name: 'kongzhi',
age: 30,
test: function() {
console.log('xxxxxxx');
}
}
}; // 通过delegates将内部对象 xx 委托到外部对象obj上 var d = new delegates(obj, 'xx');
d.setter('name').setter('age').setter('test'); // 使用setter后,就可以在obj对象上直接修改变量或函数的值了
obj.name = '123456';
obj.age = '31';
obj.test = function() {
console.log('yyyy');
} // 在外部对象obj修改完成后,我们再使用 外部对象[内部对象][变量] 这种方式获取值, 就可以看到值更新了
console.log(obj.xx.name); // 123456
console.log(obj.xx.age); // 31
obj.xx.test(); // yyyy 1. 同样的道理,使用 __defineSetter__方法来监听对象值发生改变,如果对象值发生改变的话,就返回
this[target][name] = val; 把值赋值进去。最后返回this对象。
*/
Delegator.prototype.setter = function(name){
var proto = this.proto;
var target = this.target;
this.setters.push(name); proto.__defineSetter__(name, function(val){
return this[target][name] = val;
}); return this;
}; /**
* Delegator fluent accessor
*
* @param {String} name
* @return {Delegator} self
* @api public
*/
/*
该方法的作用是,如果该方法传了参数的话,那么它的含义是修改该变量的值,如果没有传入参数的话,那么
它的作用是获取该参数的值。
使用demo如下:
const obj = {
xx: {
name: 'kongzhi',
age: 30,
test: function() {
console.log('xxxxxxx');
}
}
}; // 通过delegates将内部对象 xx 委托到外部对象obj上
var d = new delegates(obj, 'xx');
d.fluent('name').fluent('age'); // 无参数 获取该对象的值
console.log(obj.name()); // kongzhi
console.log(obj.age()); // 30 // 有参数,就是修改对应的值
obj.name('11111')
obj.age(31) console.log(obj.xx.name); // 11111
console.log(obj.xx.age); // 31 1. 当我像如上demo一样,使用 d.fluent('name').fluent('age');后,会依次保存到 this.flunts数组中。
2. 然后返回一个函数,如下代码:
obj['name'] = function(val) {
if ('undefined' != typeof val) {
this[target][name] = val;
return this;
} else {
return this[target][name];
}
}
如果值没有传递电话,就直接返回 this[target][name]; 即:obj['xx']['name'];
如果传递了值的话,就把值赋值到对象里面去,如代码:this[target][name] = val; 即:obj['xx']['name'] = val;
*/
Delegator.prototype.fluent = function (name) {
var proto = this.proto;
var target = this.target;
this.fluents.push(name); proto[name] = function(val){
if ('undefined' != typeof val) {
this[target][name] = val;
return this;
} else {
return this[target][name];
}
}; return this;
};
koa2--delegates模块源码解读的更多相关文章
- Abp 审计模块源码解读
Abp 审计模块源码解读 Abp 框架为我们自带了审计日志功能,审计日志可以方便地查看每次请求接口所耗的时间,能够帮助我们快速定位到某些性能有问题的接口.除此之外,审计日志信息还包含有每次调用接口时客 ...
- 分布式事务中间件 Fescar—RM 模块源码解读
前言 在SOA.微服务架构流行的年代,许多复杂业务上需要支持多资源占用场景,而在分布式系统中因为某个资源不足而导致其它资源占用回滚的系统设计一直是个难点.我所在的团队也遇到了这个问题,为解决这个问题上 ...
- koa2源码解读及实现一个简单的koa2框架
阅读目录 一:封装node http server. 创建koa类构造函数. 二:构造request.response.及 context 对象. 三:中间件机制的实现. 四:错误捕获和错误处理. k ...
- Webpack探索【16】--- 懒加载构建原理详解(模块如何被组建&如何加载)&源码解读
本文主要说明Webpack懒加载构建和加载的原理,对构建后的源码进行分析. 一 说明 本文以一个简单的示例,通过对构建好的bundle.js源码进行分析,说明Webpack懒加载构建原理. 本文使用的 ...
- Webpack探索【15】--- 基础构建原理详解(模块如何被组建&如何加载)&源码解读
本文主要说明Webpack模块构建和加载的原理,对构建后的源码进行分析. 一 说明 本文以一个简单的示例,通过对构建好的bundle.js源码进行分析,说明Webpack的基础构建原理. 本文使用的W ...
- koa源码解读
koa是有express原班人马打造的基于node.js的下一代web开发框架.koa 1.0使用generator实现异步,相比于回调简单和优雅和不少.koa团队并没有止步于koa 1.0, 随着n ...
- AFNetworking 3.0 源码解读(一)之 AFNetworkReachabilityManager
做ios开发,AFNetworking 这个网络框架肯定都非常熟悉,也许我们平时只使用了它的部分功能,而且我们对它的实现原理并不是很清楚,就好像总是有一团迷雾在眼前一样. 接下来我们就非常详细的来读一 ...
- AfNetworking 3.0源码解读
做ios开发,AFNetworking 这个网络框架肯定都非常熟悉,也许我们平时只使用了它的部分功能,而且我们对它的实现原理并不是很清楚,就好像总是有一团迷雾在眼前一样. 接下来我们就非常详细的来读一 ...
- seajs 源码解读
之前面试时老问一个问题seajs 是怎么加载js 文件的 在网上找一些资料,觉得这个写的不错就转载了,记录一下,也学习一下 seajs 源码解读 seajs 简单介绍 seajs是前端应用模块化开发的 ...
随机推荐
- leetcode — remove-duplicates-from-sorted-array-ii
/** * Source : https://oj.leetcode.com/problems/remove-duplicates-from-sorted-array-ii/ * * * Follow ...
- git第三节----git status与git diff
@ git status主要检索本地仓库的文件更新状态 @ git diff 主要是查看文件更新的具体内容 首先我们需要了解下文件状态类型,分为以追踪文件和未追踪文件 已追踪文件:在仓库之前的版本快照 ...
- python 使用 thrift 教程
一.前言: Thrift 是一种接口描述语言和二进制通信协议.以前也没接触过,最近有个项目需要建立自动化测试,这个项目之间的微服务都是通过 Thrift 进行通信的,然后写自动化脚本之前研究了一下. ...
- 小程序开发笔记【一】,查询用户参与活动列表 left join on的用法
今天在做一个用户活动查询功能的时候,查询参与的活动.正常,使用egg-mysql查询数据一般会这么写 result = await this.app.mysql.select('tb_activity ...
- js报错:Uncaught SyntaxError: Unexpected string
一.问题 今天在写jsp页面时,发现加上某段代码后,页面的其它js就失效了,死活出不来,然后打开谷歌浏览器发现,页面js报如下错误: Uncaught SyntaxError: Unexpected ...
- 在Jenkins管道中添加Webhook
你有没有尝试过在Jenkins中添加GitHub webhook?在这篇博客中,我将演示在您的管道中添加webhook的最简单方法. 首先,什么是webhook?webhook的概念很简单.webho ...
- loj#6074. 「2017 山东一轮集训 Day6」子序列(矩阵乘法 dp)
题意 题目链接 Sol 设\(f[i][j]\)表示前\(i\)个位置中,以\(j\)为结尾的方案数. 转移的时候判断一下\(j\)是否和当前位置相同 然后发现可以用矩阵优化,可以分别求出前缀积和逆矩 ...
- SAP MM 无价值物料管理的一种实现思路
SAP MM 无价值物料管理的一种实现思路 笔者所在的项目,客户工厂处于先期试生产阶段,尚未开始大规模的商业化生产,但是这并不影响客户集团总部的SAP项目实施.笔者于7月初加入该工厂的第2期SAP项目 ...
- [ArcGIS API for JavaScript 4.8] Sample Code-Get Started-widgets简介
[官方文档:https://developers.arcgis.com/javascript/latest/sample-code/intro-widgets/index.html] 一.Intro ...
- 虚拟机下centos7.x简易命令大全与试玩体验
OS: liunxversion: centos7.xdate: 2019-01-18 1. cd / : 进入服务器根目录2. cd . ...