javascript 类的继承

经典继承

该继承方式综合了原型链和构造函数的方式,将两者的优点集中了起来。组合继承弥补了之前原型链和盗用构造函数这两种方式各自的不足,是 JavaScript 中使用最多的继承方式。

组合继承最大的问题就是效率问题。最主要就是父类的构造函数始终会被调用两次:一次是在创建子类原型时调用,另一次是在子类构造函数中调用。本质上,子类原型最终是要包含超类对象的所有实例属性,子类构造函数只要在执行时重写自己的原型就行了。

下面是一个组合继承的例子:

 基类

 var Person = function (name, age) {

     this.name = name;

     this.age = age;

 }

 Person.prototype.test = "this is a test";

 Person.prototype.testFunc = function () {

     console.log('this is a testFunc');

}

 子类

 var Student = function (name, age, gender, score) {

     Person.apply(this, [name, age]); // 盗用构造函数

     this.gender = gender;

     this.score = score;

 }

 Student.prototype = new Person(); // 改变 Student 构造函数的原型对象

 Student.prototype.testStuFunc = function () {

     console.log('this is a testStuFunc');

 }

 测试

 var zhangsan = new Student("张三", 18, "男", 100);

 console.log(zhangsan.name); // 张三

 console.log(zhangsan.age); // 18

 console.log(zhangsan.gender); // 男

 console.log(zhangsan.score); // 100

 console.log(zhangsan.test); // this is a test

 zhangsan.testFunc(); // this is a testFunc

 zhangsan.testStuFunc(); // this is a testStuFunc

圣杯继承

圣杯模式的继承解决了组合继承的一些问题,其基本思路就是不通过调用父类构造函数来给子类原型赋值,而是取得父类原型的一个副本,然后将返回的新对象赋值给子类原型。

下面是圣杯模式的示例:

 // target 是子类,origin 是基类

 // target ---> Student, origin ---> Person

 function inherit(target, origin) {

     function F() { }; // 没有任何多余的属性

     // origin.prototype === Person.prototype, origin.prototype.constructor === Person 构造函数

     F.prototype = origin.prototype;

     // 假设 new F() 出来的对象叫小 f

     // 那么这个 f 的原型对象 === F.prototype === Person.prototype

     // 那么 f.constructor === Person.prototype.constructor === Person 的构造函数

     target.prototype = new F();

     // 而 f 这个对象又是 target 对象的原型对象

     // 这意味着 target.prototype.constructor === f.constructor

     // 所以 target 的 constructor 会指向 Person 构造函数

     // 我们要让子类的 constructor 重新指向自己

     // 若不修改则会发现 constructor 指向的是父类的构造函数

     target.prototype.constructor = target;

 }

基类 

var Person = function (name, age) {

     this.name = name;

     this.age = age;

 }

 Person.prototype.test = "this is a test";

 Person.prototype.testFunc = function () {

     console.log('this is a testFunc');

 }

子类

var Student = function (name, age, gender, score) {

     Person.apply(this, [name, age]);

     this.gender = gender;

     this.score = score;

 }
 inherit(Student, Person); // 使用圣杯模式实现继承

 // 在子类上面添加方法

 Student.prototype.testStuFunc = function () {

     console.log('this is a testStuFunc');

 }

测试

 var zhangsan = new Student("张三", 18, "男", 100);

console.log(zhangsan.name); // 张三

 console.log(zhangsan.age); // 18

 console.log(zhangsan.gender); // 男

 console.log(zhangsan.score); // 100

 console.log(zhangsan.test); // this is a test

 zhangsan.testFunc(); // this is a testFunc

 zhangsan.testStuFunc(); // this is a testStuFunc

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值