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. 修改sql数据库名称

    USE master; GO DECLARE @SQL VARCHAR(MAX); SET @SQL='' SELECT @SQL=@SQL+'; KILL '+RTRIM(SPID) FROM ma ...

  2. leetcode — scramble-string

    import java.util.Arrays; /** * Source : https://oj.leetcode.com/problems/scramble-string/ * * Given ...

  3. mongodb分片扩展架构

    目录 一.简介 二.分片集群 三.数据分布策略 四.Mongos访问模式 五.Config元数据 六.分片均衡 参考文档 一.简介 MongoDB目前3大核心优势:『灵活模式』+ 『高可用性』 + 『 ...

  4. Linux svn checkout时候总报设备上没有空间

    详细报错信息:svn: 不能打开文件“weibosearch2.0.0/.svn/lock”: 设备上没有空间 但是df -h查看磁盘[root@picdata-1-2 data]# df -h文件系 ...

  5. Powershell:关于hashtable你想知道的一切

    译者语:本篇为一篇译文,详细介绍了在powershell中如何使用hashtable这种数据类型.本文为本人2018年最后一篇博文(哈哈,一年内写没写几篇),也是本人的第一次译文,有不足之处还请指教. ...

  6. CSS float的相关图文详解(一)

    大家好,作为一个刚入门的小前端,第一次写博客,很是鸡冻.由于涉猎较浅,有些知识可能说的不清楚,或者有什么错误,欢迎留言指正.我的第一篇博客写的关于css的浮动的.想必很多小伙伴特别是刚学的,对浮动有一 ...

  7. RabbitMQ是如何运转的?

    前言 之前已经介绍了RabbitMQ交换机模型的相关简单概念,都是作为此篇的基础铺垫,如果对此篇不懂的可以先看我上一篇的介绍认识RabbitMQ交换机模型,或者联系评论,分享<RabbitMQ实 ...

  8. Java开发笔记(六十一)Lambda表达式

    前面介绍了匿名内部类的简单用法,通过在sort方法中运用匿名内部类,不但能够简化代码数量,还能保持业务代码的连续性.只是匿名内部类的结构仍显啰嗦,虽然它省去了内部类的名称,但是花括号里面的方法定义代码 ...

  9. Android开发——Notification通知的使用及NotificationCopat.Builder常用设置API

    想要看全部设置的请看这一篇 [转]NotificationCopat.Builder全部设置 常用设置: 设置属性 说明 setAutoCancel(boolean autocancel) 设置点击信 ...

  10. 深入理解JavaScript作用域和作用域链

    前言 JavaScript 中有一个被称为作用域(Scope)的特性.虽然对于许多新手开发者来说,作用域的概念并不是很容易理解,本文我会尽我所能用最简单的方式来解释作用域和作用域链,希望大家有所收获! ...