1. 访问者模式
1.1 定义
访问者模式( visitor),可以在不改变对象的前提向, 定义作用于对象的新操作.
这个模式在面向对象强类型的语言中实现起来还是比较麻烦的, 但是在JavaScript这种弱类型语言来说实现起来非常简单, 因为访问者模式几乎是原生实现的
1.2 作用
- 让对象的执行算法随着访问者的改变而改变
- 增强代码的可扩展性
- 将稳定数据结构和具体的操作进行解耦
1.3 应用场景
- 场景一
let person = {
// 给执行上下文this对象添加两个属性
addAttr(){
this.sex = '男';
this.hobby = '打篮球'
}
}
person.addAttr();
let obj = {};
obj.addAttr.call(obj)
对象person拥有addAttr方法, 作用是个对象添加两个属性, 现在我们想给对象obj也添加这两个属性, 但我们不希望obj拥有addAttr方法, 此时我们可以使用call指定一下addAttr执行上下文this文为obj就可以解决,因此我们可以看到原生JavaScript属性访问者模式非常简单,借助call/apply就可以实现
- 场景二
JavaScript里面用很多原生的API都采用访问者模式的操作, 就比如数组相关的操作
我们都知道函数的arguments对象是一个类数组对象,它有length属性,长得很像数组,但他不是一个真正的数组类型,所以它的原型上没有数组原型上许多好用的方法. 但是我们借用访问者模式来调用数组原生的各种好用的api;
function add(){
return Array.prototype.reduce.call(arguments,(total,next) =>{
return total + next
},0)
}
console.log(add(1, 2, 3, 4, 5, 6))// 21
通过借用数组原型的reduce方法利用call方法指定对应的context为arguments, 并传入对应的回调函数参数,我们实现了对类数组的每一项累加操作.
我们都知道数组用push方法, 现在我们希望普通对象x也有push方法也能添加数组属性和length
let Visitor = {
push(obj,value){
return Array.prototype.push.call(obj,value)
}
}
let x = {};
Visitor.push(x,111);
console.info(x)//{0: 111, length: 1}
上面的代码我们通过定义了Visitor访问者对象,并为其添加了push方法, 内部原理还是借用call方法来改变数组push方法的执行上下文, 实现人普通对象也能调用数组的push方法.
总结: 通过访问者模式我们可以在对象的方法上定义新的操作, 而且不会改变原对象的原有形式,这种模式非常灵活,访问者模式使得我们可以很容易的在对象的方法上定义新操作,客户端只需要对应的访问者对象就能实现不同的操作.
网友评论