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是前端应用模块化开发的 ...
随机推荐
- 【Java基础】【15Colletion集合】
15.01_集合框架(对象数组的概述和使用) A:案例演示 需求:我有5个学生,请把这个5个学生的信息存储到数组中,并遍历数组,获取得到每一个学生信息. Student[] arr = new Stu ...
- leetcode — same-tree
import java.util.Stack; /** * Source : https://oj.leetcode.com/problems/same-tree/ * * * Given two b ...
- Magicodes.WeiChat——发送模板消息
在微信开发中,经常会使用到模板消息.因此框架中对此进行了一些封装,并且提供了后台操作界面以及日志查看等功能,下面开始逐步介绍开发操作以及使用. 微信公众平台配置 首先,需要申请开通模板消息功能,如下图 ...
- 流式大数据计算实践(3)----高可用的Hadoop集群
一.前言 1.上文中我们已经搭建好了Hadoop和Zookeeper的集群,这一文来将Hadoop集群变得高可用 2.由于Hadoop集群是主从节点的模式,如果集群中的namenode主节点挂掉,那么 ...
- 大数据利器Hive
序言:在大数据领域存在一个现象,那就是组件繁多,粗略估计一下轻松超过20种.如果你是初学者,瞬间就会蒙圈,不知道力往哪里使.那么,为什么会出现这种现象呢?在本文的开头笔者就简单的阐述一下这种现象出现的 ...
- 算法工程师想进一步提高竞争力?向TensorFlow开源社区贡献你的代码吧
算法工程师为什么也要向社区贡献代码? [作者:DeepLearningStack,阿里巴巴算法工程师,开源TensorFlow Contributor] “做算法的人要熟悉算法框架源码吗?算法工程师难 ...
- C#的多样性,new,sealed方法
class A{ public virtual void Display(){Console.WriteLine("A");} } class B:A{ public new vo ...
- Go中多个返回值的技巧
直接上代码看个例子吧: package main import "fmt" //返回 X+Y 和 X*Y func Computer(X, Y int) (int, int) { ...
- 通过多线程处理提高Redis性能
Redis通常被称为单进程单线程模型. 这不是真的! Redis还运行多个后端线程来执行后端清理工作,例如清理脏数据和关闭文件描述符.在Redis中,主线程负责主要任务,包括但不限于:接收来自客户端的 ...
- TypeScript,初次见面,请多指教 ?
为什么用 TS ? 说实话,最开始并没有想把 TS 用到实际项目中来,一来是感觉"类型"会限制 JS 的优势(好吧,就是浪写浪惯了):二来听闻 TS + Redux 的酸爽滋味,有 ...