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模块源码解读的更多相关文章

  1. Abp 审计模块源码解读

    Abp 审计模块源码解读 Abp 框架为我们自带了审计日志功能,审计日志可以方便地查看每次请求接口所耗的时间,能够帮助我们快速定位到某些性能有问题的接口.除此之外,审计日志信息还包含有每次调用接口时客 ...

  2. 分布式事务中间件 Fescar—RM 模块源码解读

    前言 在SOA.微服务架构流行的年代,许多复杂业务上需要支持多资源占用场景,而在分布式系统中因为某个资源不足而导致其它资源占用回滚的系统设计一直是个难点.我所在的团队也遇到了这个问题,为解决这个问题上 ...

  3. koa2源码解读及实现一个简单的koa2框架

    阅读目录 一:封装node http server. 创建koa类构造函数. 二:构造request.response.及 context 对象. 三:中间件机制的实现. 四:错误捕获和错误处理. k ...

  4. Webpack探索【16】--- 懒加载构建原理详解(模块如何被组建&如何加载)&源码解读

    本文主要说明Webpack懒加载构建和加载的原理,对构建后的源码进行分析. 一 说明 本文以一个简单的示例,通过对构建好的bundle.js源码进行分析,说明Webpack懒加载构建原理. 本文使用的 ...

  5. Webpack探索【15】--- 基础构建原理详解(模块如何被组建&如何加载)&源码解读

    本文主要说明Webpack模块构建和加载的原理,对构建后的源码进行分析. 一 说明 本文以一个简单的示例,通过对构建好的bundle.js源码进行分析,说明Webpack的基础构建原理. 本文使用的W ...

  6. koa源码解读

    koa是有express原班人马打造的基于node.js的下一代web开发框架.koa 1.0使用generator实现异步,相比于回调简单和优雅和不少.koa团队并没有止步于koa 1.0, 随着n ...

  7. AFNetworking 3.0 源码解读(一)之 AFNetworkReachabilityManager

    做ios开发,AFNetworking 这个网络框架肯定都非常熟悉,也许我们平时只使用了它的部分功能,而且我们对它的实现原理并不是很清楚,就好像总是有一团迷雾在眼前一样. 接下来我们就非常详细的来读一 ...

  8. AfNetworking 3.0源码解读

    做ios开发,AFNetworking 这个网络框架肯定都非常熟悉,也许我们平时只使用了它的部分功能,而且我们对它的实现原理并不是很清楚,就好像总是有一团迷雾在眼前一样. 接下来我们就非常详细的来读一 ...

  9. seajs 源码解读

    之前面试时老问一个问题seajs 是怎么加载js 文件的 在网上找一些资料,觉得这个写的不错就转载了,记录一下,也学习一下 seajs 源码解读 seajs 简单介绍 seajs是前端应用模块化开发的 ...

随机推荐

  1. ASP.NET Core 框架源码地址

    ASP.NET Core 框架源码地址 https://github.com/dotnet/corefx 这个是.net core的 开源项目地址 https://github.com/aspnet  ...

  2. Java开发知识之JavaIO操作缓存操作

    目录 带缓存的输入/输出流 一丶简介 二丶BufferedInputStream 与 BufferedOutputString类. 2.BufferOutputStream类. 三丶BufferedR ...

  3. Nagios 监控系统架构

    Nagios 监控系统架设全攻略 简介: Nagios 全名为(Nagios Ain’t Goona Insist on Saintood),最初项目名字是 NetSaint.它是一款免费的开源 IT ...

  4. Python判断相等

    判断相等方法有好几个:== .is . isinstance .issubclass .operator 模块. == :两个对象内容是否相等. >>> a = [22,44]> ...

  5. Linux文件系统的基本结构

    Linux文件系统结构 通过下面两张图片来认识一下Linux文件系统的结构. 当前工作目录 实践: 文件名称 这些规则不仅适用于文件,也适用于文件夹. 实践: ls命令 ls命令表示列出当前工作目录的 ...

  6. Spring中BeanFactory的对象注册与依赖绑定方式

    概念 BeanFactory是spring的基础类型IOC容器,提供完整的IOC服务支持 默认采用延迟初始化策略,当客户端对象访问受管对象时,才对其进行初始化和依赖注入 理解 BeanFactory将 ...

  7. Djiango初识

    加载静态文件 在一个网页中,不仅仅只有一个 html 骨架,还需要 css 样式文件, js 执行文件以及一些图片 等.因此在 DTL 中加载静态文件是一个必须要解决的问题.在 DTL 中,使用 st ...

  8. 网络最大流算法—EK算法

    前言 EK算法是求网络最大流的最基础的算法,也是比较好理解的一种算法,利用它可以解决绝大多数最大流问题. 但是受到时间复杂度的限制,这种算法常常有TLE的风险 思想 还记得我们在介绍最大流的时候提到的 ...

  9. JavaScript(二)

    本文转载自https://blog.csdn.net/xiaogeldx/article/details/85412716 JavaScript操作符 算术运算符 算术运算符有:+,-,*,/,%,+ ...

  10. 为什么AI的翻译水平还远不能和人类相比?

    为什么AI的翻译水平还远不能和人类相比? https://mp.weixin.qq.com/s/0koIt-qu9IOVxNhbFcZr1Q 作者 | SHARON ZHOU 译者 | 王天宇 编辑 ...