js的继承方式1

根据JavaScript高级程序设计一书的第六章以及JavaScript面向对象编程总结。

  在对JS的继承方式进行总结之前,先要了解一下创建对象的几种方式:工厂模式、构造函数模式、原型模式、组合模式、动态原型模式以及他们的优缺点。
  传统模式是采用Object()构造函数和对象字面量的方法创建对象,但是这样会产生大量重复代码,效率较低,于是就有了工厂模式

工厂模式

工厂模式是定义一个函数,然后在函数里面新建一个对象,然后返回该对象。

    function createShape(name){
        var o=new Object();
        o.name=name;
        o.getName=function(){
            alert(this.name);
        }
        return o;
    }
    var twoDShape=createShape('2D Shape');
    var triangle=createShape('Triangle');

这样不是新建一个对象,而是调用了一个函数,这样这两个新建对象之间没有任何联系,不能反映他们是同一个原型的实例(对象的识别问题),于是有了构造函数模式。

构造函数模式

  构造函数模式就是定义一个函数,函数名首字母大写(约定俗成),没有显示的创建对象,也没有返回一个对象,使用了new创建对象,这样就解决了对象识别问题,他们都是构造函数的实例对象,可以用constructor属性确定。

    function Shape(name){
        this.name=name;
        this.getName=function(){
            alert(this.name);
        }
    }
    var twoDShape=new Shape('2D Shape');
    var triangle=new Shape('Triangle');
    alert(twoDShape.constructor===Shape);//true
    alert(triangle.constructor===Shape);//true

但是这样一来,twoDShape和triangle都含有getName()这个方法,如果有多个实例创建,则同一种方法会在多个实例对象中重复创建,于是有了原型模式。

原型模式

  如果不了解原型链可以看一看js原型链

原型模式就是将所有属性和方法写到原型对象中,构造函数变成了空函数,所有的属性和方法都是共享的。

    function Shape(name){
    }
    Shape.prototype={
        constructor:Shape,
        name:'shape',
        shape:['2D Shape','Triangle'],
        getName:function() {
            alert(this.name);
        }
    };
    var twoDShape=new Shape();
    var triangle=new Shape();
    twoDShape.getName();//shape
    triangle.getName();//shape

原型模式也有缺点,对于原型中有引用类型值的属性比如数组、对象等,当修改其中一个实例的属性时,其余的实例的该属性也会发生变化。

    twoDShape.shape.push('Square');
    alert(twoDShape.shape);//'2D Shape,Triangle,Square'
    alert(triangle.shape);//'2D Shape,Triangle,Square'

对shape属性进行添加,会发现2个实例的属性都改变了,故单独使用原型模式不是明智的。

组合模式

  组合模式是将构造函数与原型模式进行组合,将需要共享的方法写到原型对象中,而构造函数用来定义基本的属性值,这也是大多数人都会用的模式。

    function Shape(name){
        this.name=name;
        this.shape=['2D Shape','Triangle'];
    }
    Shape.prototype={
        constructor:Shape,
        getName:function(){
            alert(this.name);
        }
    };
    var twoDShape=new Shape('2D Shape');
    var triangle=new Shape('Triangle');
    twoDShape.shape.push('Square');
    alert(twoDShape.shape);//'2D Shape,Triangle,Square'
    alert(triangle.shape);//'2D Shape,Triangle'

动态原型模式

  动态原型模式是将构造函数和原型对象进行封装,使它符合面向对象语言的同时,保持它们的优点。

    function Shape(name){
        this.name=name;
        if(typeof this.getName !="function"){
            Shape.prototype.getName=function(){
                alert(this.name);
            }
        }
    }
    var twoDShape=new Shape('2D Shape');
    var triangle=new Shape('Triangle');
    twoDShape.getName();//2D Shape
    triangle.getName();//Triangle

将所有的属性和方法均封装在构造函数中,并且通过if判断原型对象是否初始化,这样只用执行一次赋值操作。
在使用动态原型模式时,不能重写原型对象,这样会使之前创建的方法和属性都无效。

  其实JavaScript高级程序设计上还讲了寄生构造函数模式和稳妥构造函数模式。寄生构造函数与工程模式是一样的,只不过在创建实例的时候用了new,在有其他的选择下不建议使用这种模式。稳妥构造函数模式与寄生构造函数模式基本是一样的,不过在新创建实例对象时不用this以及new调用构造函数,这种模式适用于某些安全执行环境。

原文地址:https://www.cnblogs.com/aicanxxx/p/6845983.html