JS原型和继承

//所有的函数都有一个prototype属性
    function aa() {
    }
    console.info(aa.prototype);
    //这个prototype属性引用了一个对象,即原型,初始化时是一个空对象,也就是没有一个成员(即原型属性和原型方法)。
    var i = 0;
    for (j in aa.prototype) {
        console.info(j);
        i++;
    }
    alert("member: " + i);//alert出原型所有属性和方法个数。 0个属性和方法
    
    function AA() {
    
    }
    AA.prototype.name = 'leyi';
    AA.prototype.fn = function () {
        return 'hello world!'
    };
    var bb = new AA();
    //实例化对象没有原型对象,他可以通过__proto__来取得原型链上的原型属性和原型方法
    console.info(bb.prototype)//undefined
    console.info(bb.__proto__) //指向AA.prototype
    //那么获取bb的属性和方法就可以通过原型链获取AA原型上的方法属性
    console.info(bb.name === bb.__proto__.name);//leyi
    console.info(bb.fn() === bb.__proto__.fn());//hello world!
    //bb的的构造器函数就是AA.prototype.constructor
    console.info(bb.constructor === AA.prototype.constructor)//true
    //bb的的构造器函数的原型就是AA.prototype
    console.info(bb.constructor.prototype === AA.prototype)//true
    
    //继承
    
    //一、通过对象冒充实现继承
    function X(width, height) {
        this.width = width;
        this.height = height;
    }
    
    function Y(w, h) {
        this.fn = X;//让父类的构造函数成为子类的方法
        this.fn(w, h);//执行该方法,继承了X方法的width,height属性
        delete this.fn; //删掉该方法
        this.draw = function () {
            console.info(this.width + '---' + this.height);//打印继承来的两个属性
        }
    }
    new Y(100, 200).draw();//100---200
    
    //二、通过call apply实现继承,原理跟上面差不多
    function XX(width, height) {
        this.width = width;
        this.height = height;
    }
    
    function YY(w, h) {
        XX.call(this, w, h);//or XX.apply(this,[w,h]);
        this.draw = function () {
            console.info(this.width + '---' + this.height);//打印继承来的两个属性
        }
    }
    new YY(300, 400).draw();//300---400
    
    
    //三、通过原型链实现继承
    function XXX(width, height) {
        this.fn = function () {
            console.info('haha')
        }
    }
    
    function YYY() {
        this.draw = function () {
            this.fn();
        }
    }
    YYY.prototype = new XXX();
    var yyy = new YYY()
    console.info(yyy.constructor)//这里有点小问题,yyy构造器函数指向了XXX
    //YYY.prototype是YYY的原型,yyy.constructor.prototype是XXX的原型
    console.info(yyy.constructor.prototype === YYY.prototype)//false
    //修正指向
    YYY.prototype.constructor = YYY//将YYY原型的构造器设置指向为YYY构造函数
    console.info(yyy.constructor.prototype === YYY.prototype)//true
    console.info(yyy.constructor)//YYY
    yyy.draw();
    
    //混合式继承
    function XXXX(width, height) {
        this.width = width;
        this.height = height;
    }
    XXXX.prototype.halo = 'halo!'
    
    function YYYY(w, h) {
        XXXX.call(this, w, h);//通过call继承XXXX的字段属性,并将其初始化
        this.draw = function () {
            console.info(this.width + '---' + this.height);
        }
    }
    YYYY.prototype = new XXXX();
    YYYY.prototype.constructor = YYYY;
    new YYYY(666, 666).draw();//666---666
    console.info(new YYYY().halo)//halo!
    
    var cst = new YYYY()
    console.info(cst.constructor.prototype === YYYY.prototype)//true
    console.info(cst.constructor)//YYYY

  

参考:

http://www.cnblogs.com/ljchow/archive/2010/06/08/1753526.html  

http://javapolo.iteye.com/blog/1996871

原文地址:https://www.cnblogs.com/leyi/p/5846730.html