古老的面向对象编程

面向对象编程

clipboard.png

一段完整的建立类的示例javascript

// 如何建立一个类,包含有:静态属性方法,公有私有属性方法?
var Book = (function(){
    // 静态私有变量 
    var bookNum = 0; 
    
    // 静态私有方法
    function checkName(name){} 
    
    var _book = function(id, newName, newPrice) { 
        // 安全模式,防止未使用new操做符
        if(this instanceof _book){ 
            // 私有变量 方法 
            var name, price; 
            function checkID(){
            } 
            
            // 公有属性,方法 
            this.id = id; 
            this.getName = function(){ return name; }; 
            this.getPrice = function(){ return price; }; 
            this.setName = function(name){ name = name; };
            this.setPrice = function(price){ price = price; }; 
            console.log(++bookNum); 
            this.setName(newName); 
            this.setPrice(newPrice);  
        } 
        else{ 
            return new _book(id, name, price); 
        } 
    };
    
    _book.prototype = { 
        // 静态公有属性 
        isJSBook: false,
        // 静态共有方法 
        displayName: function(){ 
            console.log(this.getName());
        } 
    };
    
    return _book;
}());
使用关闭包定义静态私有变量与方法,全部实例建立过程当中都能访问到

Paste_Image.png

建立实例时,打印出累加以后的bookNumcss

当替换Book(即_book)的原型以后,以前建立的实例指向的原型并不会改变,以后在以后建立Book实例时运用新的原型

Paste_Image.png

观察b三、b4的原型html

当在原来的原型上变动以后,经过该原型建立的实例都能应用变动以后的原型

Paste_Image.png

这里定义重复了,原型上的getPrice方法将会被实例自身拥有的getPrice方法掩盖住java

继承编程

  • 方式一:类式继承: 经过将子类的原型指定为父类的实例
function SuperClass(){ 
    this.superValue = true;
}
SuperClass.prototype.getSuperValue = function(){ 
    return this.superValue;
};
function SubClass(){
    this.subValue = true;
}
SubClass.prototype = new SuperClass();
SubClass.prototype.getSubValue = function(){ return this.subValue;};

Paste_Image.png

缺点:
一、若是父类中存在引用类型属性,则会被全部子类共用,一个子类修改以后将会影响到全部子类
二、没法在实例化时为父类传递初始化参数
  • 方式二: 构造函数继承: 在子类构造函数中经过call或者apply调用父类的构造函数,实现继承父类定义的属性方法
function SuperClass(id){
    this.books = ['js', 'css', 'html'];
    this.id = id;
}
SuperClass.prototype.showBooks = function(){
    console.log(this.books.join());
};
function SubClass(id){
    SuperClass.call(this, id);
}

Paste_Image.png

缺点:
一、子类没有继承父类的原型
二、每一个实例化出来的子类对象都会单独拥有一份父类上定义的属性方法,没法复用父类的属性或者方法
  • 方式三: 组合继承: 方式一与方式二的组合模式
function SuperClass(name){
    this.name = name;
    this.books = ['js', 'css','html'];
}
SuperClass.prototype.getName = function(){
    console.log(this.name);
};
function SubClass(name, time){
    SuperClass.call(this, name);
    this.time = time;
}
SubClass.prototype = new SuperClass();
SubClass.prototype.getTime = function(){ console.log(this.time);}

Paste_Image.png

缺点:
一、父类构造函数执行了两遍
二、子类实例化出来的对象原型中重复了一次父类构造函数中的属性方法
  • 方式四: 原型式继承: 使用过渡函数做为构造函数,传入的对象做为过渡函数的原型
function inheritObject(o){
    function F(){}
    F.prototype = o;
    return new F();
}
缺点:
跟方式一有相同的缺点
  • 方式五: 寄生式继承: 在方式四的基础上进行二次封
function createBook(obj){
    var o = inheritObject(obj);
    o.getName = function(){
        console.log(this.name); 
    };
    
    return o;
}

Paste_Image.png

  • 方式六: 寄生组合式继承: 寄生式继承跟够构造函数继承的组合
function inheritPrototype(SubClass, SuperClass){
    var p = inheritObject(SuperClass.prototype);
    p.constructor = SubClass;
    SubClass.prototype = p;
}
function SuperClass(name){
    this.name = name;
    this.books = ['js', 'css','html'];
}
SuperClass.prototype.getName = function(){
    console.log(this.name);
};
function SubClass(name, time){
    SuperClass.call(this, name);
    this.time = time;
}
inheritPrototype(SubClass, SuperClass);
SubClass.prototype.getTime = function(){ console.log(this.time);
}

Paste_Image.png

子类添加原型方法只能在现有原型上一个添加

整个过程:先定义子类及父类与父类原型,而后子类原型引用父类的原型对象,而后子类在添加本身的原型方法,最后调用父类构造函数安全

相关文章
相关标签/搜索