JS实现继承 JavaScript定义一个父类:// 定义一个动物类function Animal (name) {// 属性this.name = name || ‘Animal’;// 实例方法this.sleep = function(){console.log(this.name + ‘正在睡觉!’);}}// 原型方法Animal.prototype.eat = function(food) {console.log(this.name + ‘正在吃:’ + food);};1.原型链继承核心:将父类的实例作为子类的原型function Cat(){}Cat.prototype = new Animal();Cat.prototype.name = ‘cat’;// Test Codevar cat = new Cat();console.log(cat.name);console.log(cat.eat(‘fish’));console.log(cat.sleep());console.log(cat instanceof Animal); //trueconsole.log(cat instanceof Cat); //true特点:非常纯粹的继承关系,实例是子类的实例,也是父类的实例父类新增的原型方法、属性,子类都能访问到简单,易于实现缺点:要想为子类新增属性和方法,必须要在new Animal()这样的语句之后执行(可以在cat构造函数中,为Cat实例增加实例属性)无法实现多继承来自原型对象的引用属性被所有实例共享创建子类实例时,无法向父类构造函数传参下面代码解释缺点3(注意是引用属性):function Super(){ this.val = 1; this.arr = [1];}function Sub(){ // …}Sub.prototype = new Super(); // 核心 var sub1 = new Sub();var sub2 = new Sub();sub1.val = 2;sub1.arr.push(2);alert(sub1.val); // 2alert(sub2.val); // 1 alert(sub1.arr); // 1, 2alert(sub2.arr); // 1, 22.构造继承核心:使用父类的构建函数来增强子类实例,等于复制父类的实例属性给子类(没用到原型),除了call方法,也可以用apply()function Cat(name){Animal.call(this);this.name = name || ‘Tom’;}// Test Codevar cat = new Cat();console.log(cat.name);console.log(cat.sleep());console.log(cat instanceof Animal); // falseconsole.log(cat instanceof Cat); // true特点:解决了1中,子类实例共享父类引用属性的问题创建子类实例时,可以向父类传递参数可以实现多继承(call多个父类对象)缺点:实例并不是父类的实例,只是子类的实例只能继承父类的实例属性和方法,不能继承原型属性和方法无法实现函数复用,每个子类都有父类的实例函数的副本,影响性能3.实例继承核心:为父类实例添加新特性,作为子类实例返回function Cat(name){var instance = new Animal();instance.name = name || ‘Tom’;return instance;}// Test Codevar cat = new Cat();console.log(cat.name);console.log(cat.sleep());console.log(cat instanceof Animal); // trueconsole.log(cat instanceof Cat); // false特点:不限制调用方式,不管是new 子类()还是子类(),返回的对象都具有相同的效果缺点:实例是父类的实例,不是子类的实例不支持多继承4. 拷贝继承核心:使用for…in将父类实例中的方法赋给子类实例function Cat(name){var animal = new Animal();for(var p in animal){Cat.prototype[p] = animal[p];}Cat.prototype.name = name || ‘Tom’;}// Test Codevar cat = new Cat();console.log(cat.name);console.log(cat.sleep());console.log(cat instanceof Animal); // falseconsole.log(cat instanceof Cat); // true特点:支持多继承缺点:效率较低,内存占用高(因为要拷贝父类的属性)无法获取父类不可枚举的方法(for in无法访问不可枚举的方法)5.组合继承核心:通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用function Cat(name){Animal.call(this);this.name = name || ‘Tom’;}Cat.prototype = new Animal();//组合继承需要修复构造函数的指向Cat.prototype.constructor=Cat;// Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.sleep()); console.log(cat instanceof Animal); // true console.log(cat instanceof Cat); // true特点:弥补了方式2的缺陷,可以继承实例属性、方法,也可以继承原型属性、方法既是子类的实例,也是父类的实例不存在引用属性的共享问题可传参函数可复用缺点:调用了两次父类构造函数,生成了两份实例(子类实例将子类原型上的那份屏蔽了)6.寄生组合继承核心:通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构造的时候,就不会初始化两次实例方法/属性,避免的组合继承的缺点function Cat(name){Animal.call(this);this.name = name || ‘Tom’;}(function(){// 创建一个没有实例方法的类var Super = function(){};Super.prototype = Animal.prototype;//将实例作为子类的原型Cat.prototype = new Super();//寄生组合继承需要修复构造函数的指向Cat.prototype.constructor=Cat;})(); // Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.sleep()); console.log(cat instanceof Animal); // true console.log(cat instanceof Cat); //true特点:堪称完美缺点:实现较为复杂补充:es6的class实现继承class Animal { //构造函数 constructor(props) { this.name = props.name || ‘未知’; } eat() { alert(this.name + “在吃东西…”); } } //class继承 class Bird extends Animal { //构造函数 constructor(props) { //调用实现父类的构造函数 super(props); this.name = props.name || “未知”; } fly() { alert(this.name + “在飞…”); } } var myBird = new Bird({ name: ‘鹦鹉’ }) myBird.eat() // 鹦鹉在吃东西… myBird.fly() // 鹦鹉在飞…