设想形式
1、装潢者形式
在不转变对象本身的基本上,在递次运转时期给对象动态的增加职责
//看一个简朴的例子:
Function.prototype.fn = function(fn){
var self = this;
return function(){
self.apply(this,arguments);
fn.apply(this,arguments);
}
}
function a(){
console.log('我是函数a');
}
var copyA = a.fn(function(){
console.log('我是a函数分外的功用');
})
copyA();
// 我是函数a
// 我是a函数分外的功用
//监听数组的变化
var methods=['push','pop','shift','unshift','splice','slice','sort','reverse'];
var Method = {};
for(var i=0;i<methods.length;i++){
var method = methods[i];
(function(method){
var original = Array.prototype[method];
Method[method] = function(){
console.log('监听数组的变化或许操纵函数等');
return original.apply(this,arguments);
}
})(method)
}
var list = ['a','b','c'];
list.__proto__ = Method;
list.push('d');//打印:监听数组的变化或许操纵函数等
看一个段来自javascript面向对象编程指南(第二版)中关于装潢器形式的诠释及其代码:
装潢器形式是一种组织型形式,它与对象的建立无关,主要斟酌的是怎样拓展对象的功用。也就是说,除了运用线性式(父-子-孙)继续体式格局以外,我们也可认为一个基本对象建立若干个装潢对象以拓展其功用。然后,由我们的递次自行挑选差别的装潢器,并按差别的递次运用它们。在差别的递次中我们可能会面对差别的需求,并从一样的装潢器鸠合中挑选差别的子集。
//装潢一颗圣诞树
var tree = {};
tree.decorate = function(){
console.log('tree');
}
/*接着,再定义 getDecorator()要领,该要领用于增加分外的装潢器。装潢器被完成为组织器函数,都继续自 tree 对象。*/
tree.getDecorator = function(deco){
tree[deco].prototype = this;
return new tree[deco];
};
/*下面来建立3个装潢器,我们将它设为 tree 的一个属性(以坚持全局定名空间的纯洁)。 以下对象也供应了 decorate()要领,注重它先调用了父类的decorate()要领。*/
tree.Red = function(){
this.decorate = function(){
this.Red.prototype.decorate();
// console.log(this.Red.prototype);
// console.log(this.Red.prototype.decorate);
console.log('red');
};
this.name = 'red';
}
tree.Blue = function(){
this.decorate = function(){
this.Blue.prototype.decorate();
// console.log(this.Blue.prototype.decorate);
//tree['Blue']的原型是tree,所以打印出"tree"
console.log('blue');
}
this.name = 'blue';
}
tree.Angel = function(){
this.decorate = function(){
this.Angel.prototype.decorate();
// console.log(this.Angel.prototype.decorate);
console.log('angle');
}
this.name = 'angel';
}
/*把一切的装潢器都增加到基本对象中:*/
tree = tree.getDecorator('Blue');
tree = tree.getDecorator('Angel');
tree = tree.getDecorator('Red');
/*运转:*/
tree.decorate();
//tree
//blue
//angle
//red
/*剖析:
1、实行tree = tree.getDecorator('Blue'):
tree['Blue'].prototype = tree;
tree = {decorate: ƒ, name: "blue"}
即tree['Blue']赋值给tree,tree['Blue']的原型指向tree
输出:
"tree"
"blue"
2、实行tree = tree.getDecorator('Angel'):
tree['Angel'].prototype = tree['Blue'],(这时候tree已赋值为tree['Blue'])
tree = {decorate: ƒ, name: "Angle"}
即tree['Angel']赋值给tree,tree['Angel']的原型指向tree['Blue']
输出:
"angel"
3、实行tree = tree.getDecorator('Red'):
tree['Red'].prototype = tree['Angel'],(这时候tree已赋值为tree['Angel'])
tree = {decorate: ƒ, name: "Red"}
即tree['Red']赋值给tree,tree['Red']的原型指向tree['Angel']
输出:
"red"
*/
/*
图解:从下往上顺次继续
tree = {decorate:fn,getDecorator:fn}
|
tree['Blue'].prototype//tree={decorate: ƒ, name: "blue"}
|
tree['Angel'].prototype//tree={decorate: ƒ, name: "Angle"}
|
tree['Red'].prototype//tree={decorate: ƒ, name: "Red"}
*/
2、观察者形式(偶然也称为宣布-定阅形式)
看一个段来自javascript面向对象编程指南(第二版)中关于装潢器形式的诠释及其代码:
观察者形式是一种行动型形式,主要用于处置惩罚差别对象
之间的交互通讯题目。观察者形式中通常会包括两类对象。一个或多个宣布者对象:当有主要的事变发作时,会关照定阅者。
一个或多个定阅者对象:它们跟随一个或多个宣布者,监听它们的关照,并作出
响应的回响反映
var observer = {
addSubscriber:function (callback){//增加定阅者
if(typeof callback === "function"){
this.subscribers[this.subscribers.length] = callback;
}
},
removeSubscriber:function (callback){//删除定阅者
for(var i=0;i<this.subscribers.length;i++){
if(this.subscribers[i] === callback){
delete this.subscribers[i];
}
}
},
publish:function (what) {//授受并通报数据给定阅者
for(var i=0;i<this.subscribers.length;i++){
if(typeof this.subscribers[i] === "function"){
this.subscribers[i](what);
}
}
},
make:function(o){//将恣意对象转变成一个宣布者并为其增加上述要领。
for(var i in this){//this->observer{addSubscriber: ƒ, removeSubscriber: ƒ, publish: ƒ, make:f}
if(this.hasOwnProperty(i)){//observer.hasOwnProperty('addSubscriber') -> true
o[i] = this[i];
o.subscribers = [];
}
}//o-> {addSubscriber: ƒ, removeSubscriber: ƒ, publish: ƒ, make:f,subscribers:[],o.XX}
}
};
//有个函数blogger和恣意一个函数jack
var blogger = {
writeBlogPost : function(){
var content = 'blogger';
this.publish(content);
}
};
var jack = {
read:function (what){
console.log('jack定阅: '+what);
}
};
//blogger变成宣布者
observer.make(blogger);
//jack定阅blogger
blogger.addSubscriber(jack.read);
//blogger宣布信息
blogger.writeBlogPost();
//输出:jack定阅: blogger
末了: 别的函数也能够成为宣布者,
blogger也能够增加恣意的函数为定阅者
jack也能够定阅别的宣布者
以上总结为:
1.指定一个宣布者
2.给宣布者增加缓存列表,寄存回调函数,关照定阅者
3.宣布信息时,宣布者遍历缓存表,触发寄存的回调函数
下面看个简朴的例子:
var Event = function(){
this.subs = {};
}
//增加收听者:
Event.prototype.addSubscriber=function(k,callback){
if(!this.subs[k]){
this.subs[k]=[];
}
this.subs[k].push(callback);
};
//宣布事宜:
Event.prototype.publish=function(k,item){
var fns=this.subs[k];
if(fns){//防备宣布给不存在的对象
for(var i=0;i<fns.length;i++){
fns[i](item)
}
}
}
function reader(item){
console.log(item);
console.log('我是收听的');
//console.log(arguments)
}
var event = new Event();
event.addSubscriber('a',reader)
event.addSubscriber('b',reader)
event.publish('a','publish宣布信息');
event.publish('b','publish宣布信息');//不存在的定阅事宜b
系列文章的目次:
Vue双向绑定的完成道理系列(一):Object.defineproperty
Vue双向绑定的完成道理系列(二):设想形式
Vue双向绑定的完成道理系列(三):监听器Observer和定阅者Watcher
Vue双向绑定的完成道理系列(四):补充指令剖析器compile