0
点赞
收藏
分享

微信扫一扫

javaScript设计模式-继承2

继承

在实现JS继承时需要注意一个类依赖另一个类的内部实现这样的耦合关系。如果设计的是一个供众人使用的API,最好使用类继承方式。原型的方式更简洁也更节省内存。掺元适合即要共享类的方法又不需要结对的情况。

类式继承

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

//subClass
function Author(name, books) {
    Person.call(this, name); //在子类中调用父类的构造.
    this.books = books; // Add an attribute to Author.
}

Author.prototype = new Person(); // Set up the prototype chain.
Author.prototype.constructor = Author; // Set the constructor
Author.prototype.getBooks = function() { // Add method to Author.
    return this.books;
};


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

function Author(name, books) {
    Author.superclass.constructor.call(this, name);
    this.books = books;
}
extend(Author, Person);
Author.prototype.getName = function() {
    var name = Author.superclass.getName.call(this);
    return name + ', Author of ' + this.getBooks().join(', ');
};

/* Extend function, improved.这处可以用JQUERY的EXTEND方法,比这个更好 */
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 clone(object) {
    function F() {}
    F.prototype = object;
    return new F;
}
var Person = {
    name: 'default name',
    getName: function() {
        return this.name;
    }
};
var reader = clone(Person);

如果原型中还有自己的子对象时,需要修改子对象的默认值时,最好采用工厂的创建方法。

var CompoundObject = {};
CompoundObject.string1 = 'default value',
    CompoundObject.createChildObject = function() {
        return {
            bool: true,
            num: 10
        }
    };
CompoundObject.childObject = CompoundObject.createChildObject();

var compoundObjectClone = clone(CompoundObject);
compoundObjectClone.childObject = CompoundObject.createChildObject();
compoundObjectClone.childObject.num = 5;

掺元

/*使receivingClass类具有givingClass类的所有方法*/
function augment(receivingClass, givingClass) {
    for(methodName in givingClass.prototype) {
        if(!receivingClass.prototype[methodName]) {
            receivingClass.prototype[methodName] = givingClass.prototype[methodName];
        }
    }
}
/* 使receivingClass类具有givingClass类的特定方法. */
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]) {
                receivingClass.prototype[methodName] = givingClass.prototype[methodName];
            }
        }
    }
}
//使类Author具有类BaseClass的SeriMethod方法
augment(Author, BaseClass, 'SeriMethod')

var Mixin = function() {};
Mixin.prototype = {
    serialize: function() {
    }
};

augment(Author, Mixin);//Author的代码省略了
augment(Author, Mixin, 'serialize');

var author = new Author('Ross Harmes', ['JavaScript Design Patterns']);
var serializedString = author.serialize();

方法的链式调用

定义一个构造函数,把元素作为数组保存在一个实例属性中,并让所有定义在构造函数的prototype属性所指对象中的方法都返回用以调用方法的那个实例的引用,那么就具有了进行链式调用的能力。

(function() {
  function _$(els) {
  }
  _$.prototype = {
    each: function(fn) {
      for ( var i = 0, len = this.elements.length; i < len; ++i ) {
        fn.call(this, this.elements[i]);
      }
      return this;
    },
    setStyle: function(prop, val) {
      this.each(function(el) {
        el.style[prop] = val;
      });
      return this;
    }
  };
  window.$ = function() {
    return new _$(arguments);
  };
})();

$(window).addEvent('load', function() {
  $('test-1', 'test-2').setStyle('color', 'red')
      .addEvent('click', function(e) {
      $(this).setStyle('color', 'green');
    });
});

构建一个简单的JS库框架

Function.prototype.method = function(name, fn) {
    this.prototype[name] = fn;
    return this;//指向_$
};
(function() {
    function _$(els) {
    }
    _$.prototype = {
        each: function(fn) {
            for ( var i = 0, len = this.elements.length; i < len; ++i ) {
                fn.call(this, this.elements[i]);
            }
            return this;
        },
        setStyle: function(prop, val) {
            this.each(function(el) {
                el.style[prop] = val;
            });
            return this;
        }
    };
    _$.method('show', function(){//扩展方法,这样就不必全写在原型中了
        return this;
    });
    window.installHelper = function(scope, interface) {
        scope[interface] = function() {
            return new _$(arguments);
        }
    };
})();
//定义此方法是防止$被占用
installHelper(window, '$');
var t = $('example').setStyle('color', 'green').show();//链式调用

链式调用很适合赋值操作,有时对于取值器方法,并不希望返回this,而是需要返回需要的数据,但如果不返回this就失去了链式调用的方便,所以这时可以使用callback Function。的方式。

window.API2 = window.API2 ||function(){
    var name='ld';
    this.setName = function(nn){
        name = nn;
        return this;
    };
    this.getName = function(cl){
        cl.call(this, name);//此处相当于一个return
        return this;
    }
};
var o2 = new API2;
o2.getName(a).setName('Meow').getName(a);
function a(a){
    console.log(a);
}


举报

相关推荐

0 条评论