// 定义一个父类 function Person (name) { this.name = name; this.sleep = function () { console.log('朕正在睡觉!'); } } // 在父类原型上面增加一个方法 Person.prototype.eat = function (food) { console.log('朕现在吃的食物是:' + food); }
下面为您介绍几种具体的继承方式:
原型链继承
// 定义一个婴儿来继承人的父类 function Baby () { } Baby.prototype = new Person(); Baby.prototype.name = '小端'; var baby = new Baby() console.log(baby.name); // 小端 baby.eat('milk'); // 朕现在吃的食物是:milk
优点: 简单、易于实现;父类新增的原型方法和属性子类都能访问到;
缺点: 无法实现多继承;来自原型的对象的所有属性被所有实例共享;如果为子类增加属性和方法,无法放倒构造器中;创建子类实例时无法向父类构造函数传参;
构造继承
// 定义一个婴儿来继承人的父类 function Baby (name) { Person.call(this); this.name = name || 'Coder' } let baby = new Baby(); console.log(baby.name); // Coder baby.sleep(); // 朕正在睡觉! console.log(baby instanceof Person); // false console.log(baby instanceof Baby); // true
优点: 可以实现多继承;创建子类时可以向父类传递参数;子类可以共享父类引用的属性;
缺点: 实例不是父类的实例;只能继承父类的实例属性和方法;无法实现函数复用,每个子类都有父类实例函数的副本,影响性能;
实例继承
function Baby (name) { var instance = new Person(); instance.name = name || 'Coder'; return instance; } let baby = new Baby(); console.log(baby.name); // Coder baby.sleep() // 朕正在睡觉!
优点: 不限制调用方式,返回的对象具有相同的效果;
缺点: 不支持多继承;实例是父类的实例,不是子类的实例;
拷贝继承
// 定义一个婴儿来继承人的父类 function Baby (name) { var person = new Person(); for (let p in person){ Baby.prototype[p] = person[p]; } Baby.prototype.name = name || 'Coder'; } let baby = new Baby(); console.log(baby.name); // Coder baby.sleep() // 朕正在睡觉!
优点: 支持多继承;
缺点: 效率较低,内存占用高;无法获取父类不可枚举的方法;
注意:不可枚举的方法是不能使用for in访问到的方法
组合继承
// 定义一个婴儿来继承人的父类 function Baby (name) { Person.call(this); this.name = name || 'Coder'; } Baby.prototype = new Person(); Baby.prototype.constructor = Baby; let baby = new Baby(); console.log(baby.name); // Coder baby.eat('milk'); // 朕现在吃的食物是:milk
优点: 不存在引用属性共享问题,可以传参,函数可复用;
缺点: 调用两次构造函数,生成了两份实例;
寄生组合继承
// 定义一个婴儿来继承人的父类 function Baby (name) { Person.call(this); this.name = name || 'Coder'; } (function () { let Super = function () {}; Super.prototype = Person.prototype; Baby.prototype = new Super(); })(); let baby = new Baby(); console.log(baby.name); // Coder baby.eat('milk'); // 朕现在吃的食物是:milk
优点: 整合了以上几种继承的优点;
缺点: 实现复杂;
ES6的class
ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。基本上,ES6的class可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
可以像如下定义:
class Person { constructor (name) { this.name = name; } sleep () { console.log('朕正在睡觉!'); } eat (food) { console.log('朕现在吃的食物是:' + food); } } let person = new Person('小端'); console.log(person.name); // 小端 person.eat('milk'); // 朕现在吃的食物是:milk
ES6 class的继承
// 定义一个婴儿来继承人的父类 class Baby extends Person { constructor(name){ super(name); } } let baby = new Baby('小端'); console.log(baby.name); // 小端 baby.eat('milk'); // 朕现在吃的食物是:milk
我们可以看到Class可以通过extends关键字实现继承,这比ES5的通过修改原型链实现继承,要清晰和方便很多。
我之后会单独用一章来详细讲ES6中的Class和继承。
以上所述是小编给大家介绍的Javascript中的对象和继承详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!
您可能感兴趣的文章: