javaScript设计模式探究【2】

       今天该怎么形容呢,怎一个郁闷了得,本来是报名参加蓝桥杯比赛的,刚开始都没有人参加,所以被老师教唆着去报名了,后来人多了,学院掏不起那报名费了,就弄出一个考试,悲剧的是我都块1年多没看过java了,竟然上来就给我弄出个java语法,全部都是java语法,什么编译是否正确,如若正确,输出什么,各种语法知识,最后连关键字都上来了,苦逼的我早就忘光了,结果很悲剧的没通过,你说一个蓝桥杯考的都是算法题,结果那学院的老师出成了语法题,就这么把我刷了,如果真是考算法,我自认为我还是可以的。真是太讨厌了,当初就不该受不了诱惑去报名的,狗屎,我脑子搭线了。谁让我java最基础的东西都不会呢,哎,感叹一下,哪天花点时间看看java去,老实说这种东西看看,记忆一下就会了,难道java还能比javascript还灵活,javascript我都这么深入了,一个最基础的java语法还能把我难住。。不说了,越说越郁闷。还有一件略微兴奋的事,淘宝的一个leader打电话给我了,大概问了我一下情况,不知道有没有机会进行电面,这个我还是挺期待的呢。毕竟淘宝一直都是我梦想中的公司哦。提到这,还是得感谢一下我的一位学长---天哥,是他发动资源帮我找到了一个在淘宝的学长,然后学长给了我一个淘宝leader的微博,正好看到他在招人,于是就发了简历过去,期待能有好收获吧。。屌丝,,也要有逆袭的心。。继续我们的javascript设计模式。

       1 继承----减少重复代码,弱化耦合

       1.1 类式继承--通过函数声明类、用关键字new来创建实例。

View Code
/* Class Person */
function Person(name){
    this.name = name;
}

Person.prototype.getName = function(){
    return this.name;
}

var student = new Person('John Smith');
student.getName();

/* Class  monitor. */
function Monitor(name,books){
    Person.call(this,name);
    this.book = books;    
}
Monitor.prototype = new Person();
Monitor.prototype.constructor = Monitor;
Monitor.prototype.getBooks = function(){
    return this.books;    
}

       这里用到了原型链的知识,如果这块不太懂得话,可以看看我前面的javascript学习笔记,里面有讲到prototype。简单的说,就是在访问对象的某个成员时,如果这个成员未见于当前对象,那么javascript会在prototype属性所指的对象中查找它。如果在那个对象中也没有找到,就会继续沿着原型链继续查找(类似一个指针,指向父亲对象),按照这种模式串成的那个链就是原型链。所以继承的时候只需要将子类的prototype设置为指向超类的一个实例即可。

      Monitor.prototype.constructor = Monitor是因为在让Monitor继承Person时,其constructor属性被抹除了。创建新实例的过程仍然很简单的。

      1.2 extend函数--简化类的声明,可以派生子类的整个过程包装在一个名为extend的函数中。

View Code
/* Extend function improved. */
function extend(subClass,superClass){
    var f = function(){};
    f.prototype = superClass.prototype;
    subClass.prototype = new f();
    subClass.prototype.constructor = subClass;
    
    subClass.superclass = superClass.prototype;
    if(superClass.prototype.constructor == Object.prototype.constructor){
            superClass.prototype.constructor = superClass;    
    }    
}
function Monitor(name,books){
    Monitor.superClass.constructor.call(this,name);
    this.book = books;    
}
extend(Monitor,Person);
Monitor.prototype.getBooks = function(){
    return this.books;    
}
//有了superClass属性,就可以直接调用超类中的方法,然后重定义超类的该方法
Monitor.prototype.getName = function(){
    var name = Monitor.superClass.getName.call(this);
    return name+ ', Monitor of'+this.getBooks().join(','); 
     //真漂亮的代码
}

     上面的代码真的写的非常漂亮,可以慢慢琢磨琢磨。

      1. 它添加了一个空函数f,并将用它创建的一个对象实例插入原型链中,这样做可以避免创建超类的新实例,因为它可能会比较庞大,而且有时超类的构造函数有一些副作用,或者会执行一些需要进行大量计算的任务。

      2. extend函数提供了superclass属性,这个属性可以用来弱化Monitor和Person之间的耦合,extend函数的最后三行代码确保超类的prototype的constructor属性已被正确设置(即使超类就是object类本身)。

      3.我的一点疑问,哎function Monitor中,Monitor.superclass属性是什么时候开始获得值的,因为我觉得只有在执行extend(Monitor,Person)之后,superclass才会获得值,那在这之前就调用,是否无法获得superclass的值呢。

    类式继承,用这种方式创建的对象都有一套该类的所有实例属性的副本.每一个实例方法都只存在一份,但每个对象都有一个指向它的链接

       1.3 原型式继承--直接创建一个对象,对象随后可以被新的对象重用

View Code
/Person prototype Object.*/
var Person = {
    name:'default name',
    getName:function(){
        return this.name;    
    }    
};   //Person是一个对象字面量
Monitor = clone(Monitor);
Monitor.books = [];
Monitor.getBooks = function(){
    return this.books;    
}

var author = [];

author[0] = clone(Author);
author[0].name = 'Tony lp';
author[0].books = ['JavaScript 设计模式'];

      clone函数可以用来创建新的类Person对象,它会创建一个空对象,而该对象的原型对象被设置为Person。这就意味着在这个新对象中查找某个方法或属性时,如果找不到,那么查找过程会在其原型对象中继续进行。一个克隆并非原型对象的一份完全独立的副本,它只是一个以那个对象为原型对象的一个空对象而已。具有读写不对等性,读取的时候,如果没有直接为实例化的,那么所得到的是其原型对象的同名属性值,而在写入的时候,则是直接为author[0]对象定义一个新属性。

      有必要说一下clone函数。从中可以看出prototype属性就是用来指向原型对象的,通过原型链接机制,它提供了到所有继承而来的成员的连接。

/* clone function */
function clone(Object){
    function F(){}
    F.prototype = Object;
    return new F();    
}

     1.4 类式继承和原型继承的对比

     包括javascript程序员在内的整个程序员群体对类式继承都比较熟悉,几乎所有用面向对象方式编写的javascript代码中都用到了这种继承范型。在各种流行语言中只有javascript使用原型式继承,因此可能很多人都从没用过这种继承。对象具有自己的原型对象的反向链接。但是那些高级javascript程序员总有一天需要懂得原型式继承的工作机制。

      原型式继承更能节约内存。原型链查找成员的方式使得所有克隆出来的对象都共享每个属性和方法的唯一一份实例。

      1.5 掺元类--一种重用代码的方法不需要用到严格的继承。如果想要一个函数用到多个类中,可以通过扩充的方式让这些类共享该函数。实际做法:先创建一个包含各种通用方法的类,然后再用它扩充其他类,这种包含通用方法的类称为掺元类。

View Code
/*这个Mixin类只有一个名为Serialize的方法。这个方法遍历this对象的所有成员
    并将它们的值组织为一个字符串输出。类似于toString方法
*/
var Mixin = function(){};
Mixin.prototype = {
        Serialize:function(){
            var output = [];
            for(key in this){
                output.push(key+":"+this[key]);    
            }
            return output.join(',');
        }    
}

augment(Monitor, Mixin);
var author = new Monitor('tony lp', ['javascript Design Patterns']);
var serializedString = Monitor.serialize();

function augment(receivingClass, givingClass){
    if(Arguments[2]){ //only give certain methods
        for(var i = 2, len = Arguments.length; i<len; i++){
            receivingClass.prototype[Arguments[i]]=givingClass.prototype[Arguments[i]];
        }
    }
    else{   //give all methods
        for(methodName in givingClass.prototype){
            if(!receivingClass.prototype[methodName]){
                receviingClass.prototype[methodName] = givingClass.prototype[methodName];    
            }    
        }
    }
}

      现在就可以用agument(Monitor, Mixin,'Serialize');这条语句达到只为Monitor类添加一个serialize方法的目的。

     Monitor类的实例现在就可以调用serialize方法,这可以被视为多亲继承在javascript中的一种实现方式,javascript中不允许一个子类继承多个超类,一个对象只能拥有一个原型对象。但是这种方法可以实现多继承的效果。

     好了,差不多继承的东西讲完了,感觉挺复杂,最主要的用到了prototype,如果原型链了解的还不是很详细,那么这些东西还是晚点再接触吧。

     明天如果没事的话,我会写一个demo,通过上面三种方式分别实现edit-in-place,如果看过我前面dataTable控件的博文的话,应该会对文本编辑这块有印象,dataTable插件里面自带了一个jquery.jeditable.js,我也会分析一下它是通过哪种方式实现的,但是估计那篇博文代码较多,可能不太能通过博客园发表到首页。再说吧。。

     好了,就这样。其实我最想学的是单体模式,Module模式。还有继续推进大家看看汤姆大叔的深入理解javascript,现在每天都至少看一篇,明天就可以进入他讲的设计模式篇了。印照着学习吧。

 以上全部都属个人原创,请大家转载的时候附上原创链接: http://www.cnblogs.com/tonylp

原文地址:https://www.cnblogs.com/tonylp/p/2983635.html