自定义对象之间的原型链继承

 

JavaScript中,继承的对象函数并不是通过复制而来,而是通过原型链继承(通常被称为 原型式继承 —— prototypal inheritance)

1.创建父类Person,并给Person函数的原型(prototype)添加了greeting和copy的方法。

// copy返回的其实是 new Person.prototype.constructor()

function Person(first, last, age) {
        this.name = {
          first,
          last
        };
        this.age = age;
}
Person.prototype.greeting = function() {
        alert('Hi! I\'m ' + this.name.first + '.');
};
Person.prototype.copy = function() {
        return new this.constructor(this.name.first, this.name.last, this.age);
};

2. 创建Teacher继承Person(构造器和原型(prototype)的引用)。

 2.1 Teacher继承Person构造器,并且添加了Teacher构造器属性subject

function Teacher (first, last, age, subject) {
        Person.call(this, first, last, age); //继承Person构造器属性
        this.subject = subject || '';
}

2.2 Teacher继承Person的原型(prototype)

Teacher.prototype = Person.prototype;

或者  (没有明白为什么要这样)

Teacher.prototype = Object.create(Person.prototype); 
//Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__。 
Teacher.prototype.constructor = Teacher;

每一个函数对象(Function)都有一个prototype属性,并且只有函数对象有prototype属性,因为prototype本身就是定义在Function对象下的属性。当我们输入类似var person1=new Person(...)来构造对象时,JavaScript实际上参考的是Person.prototype指向的对象来生成person1。另一方面,Person()函数是Person.prototype的构造函数,也就是说Person===Person.prototype.constructor(不信的话可以试试)。

在定义新的构造函数Teacher时,我们通过function.call来调用父类的构造函数,但是这样无法自动指定Teacher.prototype的值,这样Teacher.prototype就只能包含在构造函数里构造的属性,而没有方法。因此我们将Person.prototype作为Teacher.prototype的原型对象,使之与Teacher关联。

任何您想要被继承的方法都应该定义在构造函数的prototype对象里,并且永远使用父类的prototype来创造子类的prototype,这样才不会打乱类继承结构。

2.3 实例化Teacher对象,如果Person属性修改了的话,Teacher也会同步更新

//为Person添加了一个新的原型方法setName
Person.prototype.setName = function (g) {
  this.gender = g
}

var a = new Teacher();
console.log(a);
/*
* 打印结果如下
* {
*   name: {},
*   age: undefined,
*   gender: undefined,
*   interests: undefined,
    subject: "",
    _proto: {
       greeting: fn(),
       copy: fn (),
       setName: fn(),
        constructor: ƒ Teacher(first, last, age, gender, interests, subject)
        __proto__: Object
    }
* }
*/

3. 错误原型继承: 这里this.propotype = Person.prototype;只是添加了一个构造器属性prototype,并不是对Person原型的继承

function Teacher (first, last, age, subject) {
        Person.call(this, first, last, age); //继承Person构造器属性
        this.propotype = Person.prototype;
        this.subject = subject || '';
}
Teacher.prototype.greeting = function () {
  alert('ddddd')
}
var a = new Teacher();
console.log(a);
/*
* 打印结果如下
* {
*   name: {},
*   age: undefined,
*   gender: undefined,
*   interests: undefined,
    subject: "",
    _proto: { //依旧是Teacher的原型,而不是Person的原型
        constructor: ƒ Teacher(first, last, age, gender, interests, subject)
        __proto__: Object
    },
    prototype: { // 因为this.prototype = Person.prototype, 通过实例a调用的时候,this指代的实例a,相当于给a添加了一个新的属性prototpye,并不是修改了Teacher的原型
        greeting: fn(),
        copy: fn(),
        constructor: ƒ Person(first, last, age, gender, interests, subject),
        __proto__: {}
   }
* }
*/

 

转载于:https://my.oschina.net/u/4085373/blog/3027521

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值