javascript继承

继承

许多面向对象语言都支持接口继承和实现继承两种方式,但是ECMAScript只支持实现继承,而且是依靠原型链来实现。

  1. 理解原型对象
    function Person(){
       Person.prototype.name = "Nicholas";
       Person.prototype.age = 29;
       Person.prototype.job = "Software Engineer";
       Person.prototype.sayName = function(){
           alert(this.name);
       };
    }
    var person1 = new Person();
    var person2 = new Person();
    
    alert(person1.sayName == person2.sayName); // true
    
  • 只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个prototype属性,这个属性指向函数的原型对象。在默认情况下,所有原型对象都会自动获得一个constructor(构造函数)属性,这个属性包含一个指向prototype 属性所在函数的指针。当调用构造函数创建一个新实例后,该实例对象的内部将包含一个指针(内部属性),指向构造函数的原型对象。Firefox、Safari 和Chrome 在每个对象上都支持一个属性__proto__;要明确的真正重要的一点就是,这个连接存在于实例与构造函数的原型对象之间,而不是存在于实例与构造函数之间。
    总的来说,构造函数、原型和实例的关系:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针constructor和其它添加的属性、方法,而实例都包含一个指向原型对象prototype的内部指针。
  • 在我们调用person1.sayName()的时候,会先后执行两次搜索。首先搜索实例person1是否有sayName属性,如果没有就搜索person1的原型。
    虽然可以通过对象实例访问保存在原型中的值,但不能通过对象实例重写原型中的值。如果在实例中添加一个与实例原型属性同名的属性,那就会在实例中创建该属性,并屏蔽原型中的属性。
    person1.name = "Greg";
    alert(person1.name); // "Grey"---来自实例
    
    delete person.name;
    alert(person1.name); // "Nicholas"---来自原型
    // 使用delete操作符删除了person1.name  
    
  • 我们可以通过isPrototypeOf()方法来确定对象之间是否存在这种关系
    alert(Person.prototype.isPrototypeOf(person1)); //true
    
  • ECMAScript 5 增加了一个新方法,叫Object.getPrototypeOf(),在所有支持的实现中,这个方法可以返回属性的值。Object.getPrototypeOf()可以方便地取得一个对象的原型,而这在利用原型实现继承的情况下非常重要。
    alert(Object.getPrototypeOf(person1) == Person.prototype); //true
    alert(Object.getPrototypeOf(person1).name); 
    
  • 使用hasOwnProperty()方法可以检测一个属性是存在于实例中,还是存在于原型中。这个方法(从Object 继承来的)只在给定属性存在于对象实例中时,才会返回true。
    alert(person1.hasOwnProperty("name"));
    
  • 原型与in操作符:
    由于in 操作符只要通过对象能够访问到属性就返回true,hasOwnProperty()只在属性存在于实例中时才返回true,因此只要in 操作符返回true 而hasOwnProperty()返回false,就可以确定属性是原型中的属性。
    alert("name" in person1); // true
    //两者同时使用就可知道该属性是存在对象中还是原型中
    function hasPrototypeProperty(object, name){
        return !object.hasOwnProperty(name) && (name in object);
    }   
    
  1. 原型链
    让原型对象等于另一个类型的实例,此时的原型对象将包含一个指向另一个原型的指针,相应地,另一个原型中也包含着一个指向另一个构造函数的指针。假如另一个原型又是另一个类型的实例,那么上述关系依然成立,如此层层递进,就构成了实例与原型的链条。
    function SuperObj(){ // 
        this.a = 1;
    }
    SuperObj.prototype.getSuperValue = function(){
        return this.a;
    }
    function SubObj(){
        this.b = 2;
    }
    SubObj.prototype = new SuperObj();// 继承
    SubObj.prototype.getSubValue = function(){
        return this.b;
    }
    var obj = new SubObj();
    console.log(obj.getSuperValue()); // 1
    
    定义两个类型SuperObj和SubObj,它们的主要区别是SuperObj继承了SubObj,而继承是通过创建SuperObj的实例,并将该实例赋给SubObj.prototype 实现的。实现的本质是重写原型对象,让原来存在于SuperObj的实例中的所有属性和方法,现在也存在于SubObj.prototype中了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值