zoukankan      html  css  js  c++  java
  • 理解JavaScript继承(一)

    理解JavaScript继承(一)

    我们都知道,面向对象的编程语言非常强大,之所以强大,就是其支持继承。在JavaScript中,也支持继承,而且有多种方法实现继承,比如原型链继承,借用构造函数继承,或者把原型链和借用构造函数函数组合在一起的组合继承,还有直接原型式继承,深浅拷贝继承。下面我就一一来说一说这些继承方法。

    1.原型链

    首先我们得清楚构造函数(constructor),原型对象(prototype)和实例的三者关系。

    每一个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。

    function SuperType(){
        this.property = true;
    }
            
    SuperType.prototype.getSuperValue = function(){
        return this.property;
    };
            
    function SubType(){
        this.subproperty = false;
    }
            
    //inherit from SuperType
    SubType.prototype = new SuperType();//重写原型对象,赋值为一个实例对象,获得实例对象的所有属性和方法
            
    SubType.prototype.getSubValue = function (){
        return this.subproperty;
    };
    
    var instance = new SubType();
    alert(instance.getSuperValue());   //true
    

    原型链的详细请看深入理解原型链一文

    2.借用构造函数

    function SuperType(){
        this.colors = ["red", "blue", "green"];
    }
    
    function SubType(){  
        //inherit from SuperType
        SuperType.call(this);
    }
    
    var instance1 = new SubType();
    instance1.colors.push("black");
    alert(instance1.colors);    //"red,blue,green,black"
            
    var instance2 = new SubType();
    alert(instance2.colors);    //"red,blue,green"
    

    通过借用构造函数的方法,会实现对实例属性的继承,每个实例都有它自己的属性,这些属性都是部署在自己身上的,每一个实例对象都有自己的一个副本。改变属性不会对其它实例对象的该属性造成影响。

    3.组合继承

    组合继承,有时候也叫伪经典继承,指的是将原型链和借用构造函数的技术组合到一块,从而发挥二者之长的一种继承模式。其背后的思路是使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。这样既通过在原型上定义方法实现了函数复用,又能够保证每个实例都有它自己的属性。

    function SuperType(name){
        this.name = name;
        this.colors = ["red", "blue", "green"];
    }
            
    SuperType.prototype.sayName = function(){
        alert(this.name);
    };
    
    function SubType(name, age){  
        SuperType.call(this, name);//借用构造函数实现对实例属性的继承,每个实例对象都会创建一个该属性的副本
                
        this.age = age;
    }
    
    SubType.prototype = new SuperType();//原型链实现对原型属性和方法的继承,这样它的实例实例对象都会继承原型属性方法,都相当于是指针引用,除非自己重写了一个相同的属性或者方法实现覆盖,否则修改熟悉就会出现原型链中德问题
            
    SubType.prototype.sayAge = function(){
        alert(this.age);
    };
            
    var instance1 = new SubType("Nicholas", 29);
    instance1.colors.push("black");
    alert(instance1.colors);  //"red,blue,green,black"
    instance1.sayName();      //"Nicholas";
    instance1.sayAge();       //29
            
           
    var instance2 = new SubType("Greg", 27);
    alert(instance2.colors);  //"red,blue,green"
    instance2.sayName();      //"Greg";
    instance2.sayAge();       //27`
    
    

    4.原型式继承

    原型式继承并没有使用严格意义上的构造函数,而是借助原型可以基于已有的对象创建新对象,同时还不必创建自定义类型。

    function object(o) {
        function F() {}    
        F.prototype = o;  
        return new F();
    }
    

    在object()函数内部,先创建了一个临时性的构造函数,然后将传入的对象作为这个构造函数的原型,最后返回了这个临时类型的一个新实例。本质上,是对传入其中的对象做了一次浅拷贝。

    实例

    function object(o){
        function F(){}
        F.prototype = o;
        return new F();
    }
            
    var person = {
        name: "Nicholas",
        friends: ["Shelby", "Court", "Van"]
    };
            
    var anotherPerson = object(person);
    anotherPerson.name = "Greg";
    anotherPerson.friends.push("Rob");
            
    var yetAnotherPerson = object(person);
    yetAnotherPerson.name = "Linda";
    yetAnotherPerson.friends.push("Barbie");
            
    alert(person.friends);   //"Shelby,Court,Van,Rob,Barbie"
    

    原型式继承要求你必须有一个对象作为另一个对象的基础,通过把一个对象传递给object()函数,然后再根据具体需求对得到的对象加以修改(修改原来的,或者添加新的属性方法)即可。

    在ECMAScript5中,新增了一个Object.create()方法规范了原型式继承,这个方法接受两个参数:一个用作新对象原型的对象和(可选的)一个为新对象定义额外属性的对象。在传入一个参数的情况下,Object.create()与object()方法的行为相同。

    实例

    var person = {
        name: "Nicholas",
        friends: ["Shelby", "Court", "Van"]
    };
            
    var anotherPerson = Object.create(person);
    anotherPerson.name = "Greg";
    anotherPerson.friends.push("Rob");
            
    var yetAnotherPerson = Object.create(person);
    yetAnotherPerson.name = "Linda";
    yetAnotherPerson.friends.push("Barbie");
    
    alert(person.friends);   //"Shelby,Court,Van,Rob,Barbie"
    
    
  • 相关阅读:
    正则表达式语法介绍
    关系型数据库和非关系型数据库的简单对比
    lambda函数
    java基础系列--Exception异常处理
    springBoot基础系列--properties配置
    spring基础系列--JavaConfig配置
    java基础系列--Calendar类
    java基础系列--Date类
    一个特殊的List去重问题的解决方案
    Java学习笔记
  • 原文地址:https://www.cnblogs.com/YeChing/p/6349052.html
Copyright © 2011-2022 走看看