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. 性能测试-Jmeter3.1 使用技巧

    一.JMeter官网 下载地址 http://jmeter.apache.org/download_jmeter.cgi Jmeter wiki https://wiki.apache.org/jme ...

  2. springboot情操陶冶-web配置(五)

    本文讲讲mvc的异常处理机制,方便查阅以及编写合理的异常响应方式 入口例子 很简单,根据之前的文章,我们只需要复写WebMvcConfigurer接口的异常添加方法即可,如下 1.创建简单的异常处理类 ...

  3. MySQL 笔记整理(7) --行锁功能:怎么减少行锁对性能的影响?

    笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> 7) --行锁功能:怎么减少行锁对性能的影响? MySQL的行锁是在引擎层由各个引擎自己实现的.因此,并不是所有的引擎都支持行锁,如 ...

  4. 用EF的三种方式(SqlServer数据库和Oracle数据库)

    SqlServer数据库 1.DB First 现有DB,生成edmx文件 贴一下生成的model //------------------------------------------------ ...

  5. 从零开始学安全(三十四)●百度杯 ctf比赛 九月场 sqli

    先扫后台发现 两个可疑登录界面 l0gin.php login.php 猜测是第一个 用bp 抓包发现 index.php 中间有302 重定向 头文件 里面有一个 page=l0gin.php 应该 ...

  6. Maven(十五)Maven 聚合

    聚合解决的问题: 解决每个模块之间都要一个一个安装,一键安装各个模块工程 尤其时在配置继承后要先安装子模块在安装父,模块. 配置方式 自己找一个工程作为聚合工程,配置好后在聚合工程上运行Maven i ...

  7. JavaWeb学习日记----SAX解析XML

    1.SAX解析XML文档的方式: 与DOM方式解析不同,DOM方式解析是根据XML的层级结构在内存中分配一个树形结构,把xml的标签,属性和文本都封装成对象.优点是可以很方便实现增删改操作.缺点是,如 ...

  8. mac IDE输入光标变成块状 改为竖线

    mac下安装IDE后,出现“输入光标变成块状”的情况,是因为安装的时候装了ideaVim插件,改为竖线光标的方法:把ideaVim插件去掉

  9. android找不到aar包

    转载请标明出处,维权必究:https://www.cnblogs.com/tangZH/p/9939663.html  在做项目的时候引入aar包,编译的时候却提示错误(这个错误大概说的是...... ...

  10. 通过fromdata实现上传文件

    其实呢,文件上传的插件很多,可是现在做的东西要求尽量少用插件,所以就自己写了一下. 之前也用node写过对文件处理方面的东西,这次用php写着试一下. a.html文件 <!DOCTYPE ht ...