Javascript设计模式之装饰者模式详解篇(2)

this.base = AbstractDecorator; //定义一个当前对象(decorator1)的base属性,并指向函数AbstractDecorator this.base(decorated); //调用base属性指向的函数,也就是调用AbstractDecorator函数,同时传入形参decorated,形参decorated指向new出来的ConcreteClass对象

说到这里,好像还是没有分析出ConcreteDecoratorClass函数里面有performTask方法,重点是看 "this"!

ConcreteDecoratorClass函数中的this指向new出来的ConcreteDecoratorClass对象(也就是和decorator1指向同一个对象);

AbstractDecorator函数里面的this关键是看哪个对象来调用这个函数,this就指向哪个对象(从代码 “this.base = AbstractDecorator; this.base(decorated);” 中我们可以看出是new出来的ConcreteDecoratorClass对象在调用AbstractDecorator函数),所以AbstractDecorator函数里面的this指向new出来的ConcreteDecoratorClass对象(也和decorator1指向同一个对象)。

总结下来,我们会发现,在上面的代码中,不管是ConcreteDecoratorClass函数里面的this,还是AbstractDecorator函数里面的this,都指向new出来的ConcreteDecoratorClass对象。

所以,当我们执行decorator1.performTask()时,它会继续执行匿名函数中的代码(decorated.performTask();),匿名函数中的decorated形参指向new出来的ConcreteClass对象,并执行该对象的performTask方法。

最后看看实例3:

var tree = {}; tree.decorate = function () { console.log('Make sure the tree won\'t fall'); }; tree.getDecorator = function (deco) { tree[deco].prototype = this; return new tree[deco]; }; tree.RedApples = function () { this.decorate = function () { this.RedApples.prototype.decorate(); // 第7步:先执行原型(这时候是Angel了)的decorate方法 console.log('Add some red apples'); // 第8步 再输出 red // 将这2步作为RedApples的decorate方法 } }; tree.BlueApples = function () { this.decorate = function () { this.BlueApples.prototype.decorate(); // 第1步:先执行原型的decorate方法,也就是tree.decorate() console.log('Put on some blue apples'); // 第2步 再输出blue // 将这2步作为BlueApples的decorate方法 } }; tree.Angel = function () { this.decorate = function () { this.Angel.prototype.decorate(); // 第4步:先执行原型(这时候是BlueApples了)的decorate方法 console.log('An angel on the top'); // 第5步 再输出angel // 将这2步作为Angel的decorate方法 } }; tree = tree.getDecorator('BlueApples'); // 第3步:将BlueApples对象赋给tree,这时候父原型里的getDecorator依然可用 tree = tree.getDecorator('Angel'); // 第6步:将Angel对象赋给tree,这时候父原型的父原型里的getDecorator依然可用 tree = tree.getDecorator('RedApples'); // 第9步:将RedApples对象赋给tree tree.decorate(); // 第10步:执行RedApples对象的decorate方法 //Make sure the tree won't fall //Add blue apples //An angel on the top //Put on some red apples

实例3看起来很复杂,实际上分析逻辑还是和前面两个实例一样,我们可以看出实例3中一共声明了5个函数表达式。我们重点分析下下面的代码:

//tree.getDecorator('BlueApples')返回new出来的tree.BlueApples的实例对象,并将该对象赋值给空的tree对象 tree = tree.getDecorator('BlueApples'); //new出来的tree.BlueApples的实例对象的原型指向 --> 空对象tree //tree.getDecorator('Angel')返回new出来的tree.Angel的实例对象(这行代码中的第二个tree已经是上面一行代码运行结果后的tree.BlueApples的实例对象) tree = tree.getDecorator('Angel'); //new出来的tree.Angel的实例对象的原型指向 --> tree.BlueApples的实例对象 //tree.getDecorator('RedApples')返回new出来的tree.RedApples的实例对象(这行代码中的第二个tree已经是上面一行代码运行结果后的tree.Angel的实例对象) tree = tree.getDecorator('RedApples'); //new出来的tree.RedApples的实例对象的原型指向 --> tree.Angel的实例对象 //调用tree.decorate(),这里的tree已经是new出来的tree.RedApples的实例对象了。 //tree.RedApples的实例对象的decorate属性方法里面的第一行代码是 “this.RedApples.prototype.decorate()” //结合上面的分析可以得出以下的原型链结构: //this.RedApples.prototype --> tree.Angel; //tree.Angel.prototype --> tree.BlueApples; //tree.BlueApples.prototype --> 空对象tree tree.decorate();

分析到这里,就不难知道最后的输出结果了。

三、其他:

我们可以看出本文章中的装饰者模式案例中用了很多this,对this不太了解的朋友可以移步到 《深入理解javascript中的 “this”》。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwdjjx.html