javascript高级程序设计之---继承

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/codesWay/article/details/80137099
对象的继承

 1.继承的思想:关键是将一个构造函数A的原型指向给另一个构造函数B的实例本身,那么A实例将拥有(继承)B实例的所有的属性和方法(继承在原型)

  2.原理:将一个构造函数A的原型指向给另一个构造函数B的实例本身,也就意味着A原型将继承B实例本身拥有的所有的属性和方法;而对于A实例而言,A原型对象中的所有的属性和方法是A实例所共享的,也就是说A实例所共享的实例和方法就是B实例本身所拥有的一切属性和方法,这就好像A实例继承了B实例的属性和方法一样。

3.继承的一些常用的实现方法:

3.1.组合继承(最常用的继承方法)

  这里所谓的”组合“就是原型链和构造函数的技术整合到一起,分别发挥各自的优势:具体思想是:通过原型链继承原型上的属性和方法,通过借用构造函数实现对实例属性的继承。(想方设法将被继承者的实例属性”写“到继承者的实例属性值中去,这就用到了call(apply))

function SuperType(name) {
            this.name = name;
            this.colors = ["red", "blue", "green"];
        }
        SuperType.prototype.sayName = function () {
            console.log(this.name);
        }
        function SubType(name, age) {
            //继承属性(实例属性)
            // 在当前环境中执行了函数SuperType(name),
            //相当于再这里写了一下代码:this.name = name;this.colors = ["red","blue","green"];
            SuperType.call(this, name);
            this.age = age;//自己定义一个实例属性age
        }
        //通过愿原型链继承方法
        SubType.prototype = new SuperType();//要记得该实例本身是一个对象,其继承的原型中的方法sayName在该对象的__proto__属性中,因为实例.__proto__指向原型
        SubType.prototype.constructor = SubType;
        //这句话的作用是将SubType实例的constructor指向其本身(这样才正常),如果不写的话将会指向SuperType
        //因为SubType.prototype.constructor = new SuperType().constructor = SuperType
        SubType.prototype.sayAge = function () {
            console.log(this.age);
        };
        var instance1 = new SubType("Nicholas", 29);
        instance1.colors.push("black");//此时的color是一个实例属性,而不是一个原型中的属性
        console.log(instance1.colors); //"red,blue,green,black"
        instance1.sayName(); //"Nicholas";,通过原型链继承于SuperType原型中的方法
        instance1.sayAge(); //29

        var instance2 = new SubType("Greg", 27);
        console.log(instance2.colors); //"red,blue,green"
        instance2.sayName(); //"Greg";
        instance2.sayAge(); //27

3.2.原型式继承

使用Object.create(ele1,[ele2])方法;ele1:是作为新对象原型的对象,ele2是为新对象定义新属性或方法的对象(可有可无),由于ele2是为新对象直接定义的属性和方法,所以会覆盖与原型ele1中同名的属性和方法,ele2的写法和 Object.defineProperties()中的第二个参数一样

var obj = {
            name:"张三",
            teammates:["李四","王五","李六"]
        }
        var objInstance = Object.create(obj);
        console.log(objInstance)
        // 这里obj就是作为新对象objInstance原型的对象,也就是说objInstance.__proto__指向obj
        console.log(objInstance.__proto__);//obj,新创建的对象将拥有该原型的所有的属性和方法,因为obj是作为该对象的原型,
                                            //那么原型中的所有的属性和方法都将被实例对象所共享;
        console.log(objInstance.name)//张三,访问的是原型obj中的属性,因为原型中的属性和方法被共享,所以实例能够访问对应的属性和方法;
        console.log(objInstance.teammates)//["李四","王五","李六"],理由同上



        objInstance.name = "李四";//相当于对该实例对象添加了一个实例数属性name,原型中的name属性并没有改变,因为 objInstance.name保存的是一个基本类型的值;
        objInstance.teammates.push("张千子")//原型中的对应属性将会被改变,因为objInstance.teammates保存的是一个指针,指向原型中的teammates,所以相当于给原型中的teammates
                                           //属性执行了push方法
        objInstance.teammates = ["李白","杜甫"];//原指针断了,现在objInstance.teammates指针指向新的数组,相当于给对象objInstance设置了一个新的实例属性teammates,
                                            //但是原型中的teammates属性并没有发生改变,
        console.log(objInstance)//有两个实例属性和原型
        console.log(obj)//teammates属性已经发生了改变,变成了["李四","王五","李六","张千子"];





        var objInstance1 = Object.create(obj,{
            name:{
                value:"呵呵哒"
            },
            sex:{
                value:"未知"
            }
        })
        console.log(objInstance1)//不用多解释了吧

3.3.寄生式继承

说白了就是封装一个函数,该函数通过接收一个来作为新对象基础对象的参数来创建一个新对象,然后在函数体内”增强“新对象(为新对象新增新的属性和方法),最后返回新对象即可。

//该函数的目标是创建一个新的空对象,该空对象将继承param的方法和属性
        function object(param){
            function F(){};//构造函数
            F.prototype = param;//构造函数F的原型指向了param对象,也就意味着F的实例也将拥有param对象所拥有的属性和方法(共享于原型中的属性和方法)
           console.log(new F().constructor)//Object构造函数
            return new F()//空对象,该空对象实例将通过原型继承param里面的属性和方法
        }

        function createObj(baseObj){
            var newObj = object(baseObj);//产生了一个新的对象
            newObj.height = 170;//为该对象添加新的属性和方法,新的属性或者方法将是实例属性和方法
            return newObj//return 出新的对象
        }
        var base = {
            name:"张三",
            age:25
        }
        console.log(createObj(base))

3.4.寄生组合式继承

即通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。

其背后的基本思路是:不必为了指定子类型的原型而调用超类型的构造函数,我们所需要的无非就是超类型原型的一个副本而已。本质上,就是使用寄生式继承来继承超类型的原型,然后再将结果指定给子类型的原型。

//函数封装
        function inheritPrototype(subType, superType) {
            var prototype = object(superType.prototype); //一个空对象,该对象的原型指向了superType.prototype
            prototype.constructor = subType; //给上面的空对象的原型重新指定constroctor属性(为什么说constructor属性指向的空对象是原型中的呢,那是因为空对象中的实例属性没有该属性,但是原型中有)
            subType.prototype = prototype; //将 subType.prototype指向prototype,那么此时subType的原型将继承了superType原型中的属性和方法,因为constructor属性进行了重定向,所以,此时
                                           //subType的原型此时真正的正规了
        }
        /*
            该函数的作用是的得到一个空对象但是该对象却有公用属性和方法
         */
        function SuperType(name) {
            this.name = name;
            this.colors = ["red", "blue", "green"];
        }
        SuperType.prototype.sayName = function () {//Supertype实例所共有的新的属性和方法
            alert(this.name);
        };
        function SubType(name, age) {
            SuperType.call(this, name);
            this.age = age;
        }
        inheritPrototype(SubType, SuperType);
        //到这里为止,SubType的实例属性包括,name,colors,age;SubType的原型所包括的属性和方法有
        //sayName方法,和一个指向SubType原型的constructor属性....剩下的不解释啦
        SubType.prototype.sayAge = function () {
            alert(this.age);
        };
















猜你喜欢

转载自blog.csdn.net/codesWay/article/details/80137099