博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
koa 用到的delegates NPM包源码阅读
阅读量:5986 次
发布时间:2019-06-20

本文共 3550 字,大约阅读时间需要 11 分钟。

介绍

,可以帮我们方便快捷地使用设计模式当中的委托模式(Delegation Pattern),即外层暴露的对象将请求委托给内部的其他对象进行处理。

用法

基本用法就是将内部对象的变量或者函数绑定在暴露在外层的变量上,直接通过 delegates 方法进行如下委托,基本的委托方式包含:

  • getter:外部对象可以直接访问内部对象的值
  • setter:外部对象可以直接修改内部对象的值
  • access:包含 getter 与 setter 的功能
  • method:外部对象可以直接调用内部对象的函数
const delegate = require('delegates'); ​const petShop = { dog: {   name: '旺财',   age: 1,   sex: '猛汉',   bar() {     console.log('bar!');   } },}复制代码

​ // 将内部对象 dog 的属性、函数委托至暴露在外的 petShop 上

delegates(petShop, 'dog') .getter('name') .setter('age') .access('sex') .method('bar');​// 访问内部对象属性console.log(petShop.name)// => '旺财'​// 修改内部对象属性petShop.age = 2;console.log(petShop.dog.age)// => 2​// 同时访问和修改内部对象属性console.log(petShop.sex)// => '猛汉'petShop.sex = '公主';console.log(petShop.sex);// => '公主'​// 调用内部对象函数petShop.bar();// 'bar!'复制代码

除了上面这种方式之外,还可以在外部对象上添加类似 jQuery 风格的函数,即:

  • 函数不传参数的时候,获取对应的值
  • 函数传参数的时候,修改对应的值
const delegate = require('delegates');​const petShop = { dog: {   name: '旺财', },}​delegates(petShop, 'dog') .fluent('name');​// 不传参数,获取内部属性console.log(petShop.name());​// 传参数,修改内部属性// 还可以链式调用console.log( petShop.name('二哈') .name('蠢二哈') .name(););复制代码

源码学习

比较简洁。

初始化

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 = [];}复制代码

this 对象中 methods | getters | setters | flaunts 均为数组,用于记录委托了哪些属性和函数。

上述初始化函数的第一行值得引起注意: 如果 this 不是 Delegator 的实例的话,则调用 new Delegator(proto, target)。通过这种方式,可以避免在调用初始化函数时忘记写 new 造成的问题,因为此时下面两种写法是等价的:

  • let x = new Delegator(petShop, 'dog')
  • let x = Delegator(petShop, 'dog')

getter

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;};复制代码

上面代码中的关键在于 __defineGetter__ 的使用,它可以在已存在的对象上添加可读属性,其中第一个参数为属性名,第二个参数为函数,返回值为对应的属性值:

const obj = {};obj.__defineGetter__('name', () => 'elvin');​console.log(obj.name);// => 'elvin'​obj.name = '旺财';console.log(obj.name);// => 'elvin'复制代码

需要注意的是尽管 __defineGetter__ 曾被广泛使用,但是已不被推荐,建议通过 Object.defineProperty 实现同样功能,或者通过 get 操作符实现类似功能:

const obj = {};Object.defineProperty(obj, 'name', {   value: 'elvin',});​Object.defineProperty(obj, 'sex', { get() {   return 'male'; }});​const dog = { get name() {   return '旺财'; }};复制代码

Github 上已有人提出相应的 .

setter

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;};复制代码

上述代码与 getter 几乎一模一样,不过使用的是 __defineSetter__,它可以在已存在的对象上添加可读属性,其中第一个参数为属性名,第二个参数为函数,参数为传入的值:

const obj = {};obj.__defineSetter__('name', function(value) {   this._name = value;});​obj.name = 'elvin';console.log(obj.name, obj._name);// undefined 'elvin'复制代码

同样地,虽然 __defineSetter__ 曾被广泛使用,但是已不被推荐,建议通过 Object.defineProperty 实现同样功能,或者通过 set 操作符实现类似功能:

const obj = {};Object.defineProperty(obj, 'name', { set(value) {   this._name = value; }});​const dog = { set(value) {   this._name = value; }};复制代码

method

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;};复制代码

method 的实现也十分简单,只需要注意这里 apply 函数的第一个参数是内部对象 this[target],从而确保了在执行函数 this[target][name] 时,函数体内的 this 是指向对应的内部对象。

其它 提供的函数如 fluent | access 都是类似的,就不重复说明了。

参考文章

转载于:https://juejin.im/post/5ce53c956fb9a07ee062ee17

你可能感兴趣的文章
快速的React Native开发方法
查看>>
1.扩展方法2.接口的隐式实现和显式实现
查看>>
xcache 源码包编译安装
查看>>
前端开发思考与实践
查看>>
tcp/ip参数控制
查看>>
[分享]iOS开发-UIView顺时针旋转、逆时针旋转
查看>>
Conversion to Dalvik format failed with error 1的又一种情形
查看>>
Citrix VDI实战攻略之八:测试验收
查看>>
windows下安装memcached
查看>>
Java读取properties文件的思考
查看>>
分秒必争域的时间同步问题[为企业部署Windows Server 2008系列十四]
查看>>
《Storm分布式实时计算模式》——2.4 把toplogy提交到集群中
查看>>
防盗功能!Windows Phone 安全特性更上一层楼
查看>>
《Linux命令行大全》——第2章 导 航 2.1 理解文件系统树
查看>>
戴文的Linux内核专题:25 配置内核 (21)
查看>>
《Android游戏开发详解》一2.6 构建一个简单的计算器程序
查看>>
深入实践Spring Boot3.2.3 修改控制器
查看>>
《PHP、MySQL和Apache入门经典(第5版)》一一1.4 在Mac OS X上安装XAMPP
查看>>
《树莓派用户指南(第3版)》——1.2 Model A
查看>>
【SQL 性能优化】表的三种连接方式
查看>>