首先,咱们定义一个父类Animal,接下来用Cat类来实现对这个父类的继承函数
function Animal (name) { this.name = name || 'Animal'; this.sleep = function(){ console.log(this.name + '正在睡觉!'); } } Animal.prototype.eat = function(food) { console.log(this.name + '正在吃:' + food); };
核心:子类的原型对象等于父类的实例( 子类.prototype=new 父类() )性能
function Cat(){ } Cat.prototype = new Animal(); //若是等于父类prototype,就会改变(指向一样的地方) Cat.prototype.name = 'cat'; //Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.eat('fish')); console.log(cat.sleep()); console.log(cat instanceof Animal); //true console.log(cat instanceof Cat); //true
优势:this
缺点:prototype
核心:使用父类的构造函数来得到子类属性和方法,等因而复制父类的实例属性给子类(父类.call(this))code
function Cat(name){ Animal.call(this); this.name = name || 'Tom'; } // Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.sleep()); console.log(cat instanceof Animal); // false console.log(cat instanceof Cat); // true
优势:对象
核心:原型式继承的object方法本质上是对参数对象的一个浅复制。继承
function Cat(o){ function F(){} F.prototype = o; return new F(); } let cat = object(person); cat.name = "Bob"; anotherPerson.friends.push("Rob");
优势:父类方法能够复用
缺点:父类的引用属性会被全部子类实例共享,子类构建实例时不能向父类传递参数
ECMAScript 5 经过新增 Object.create()方法规范化了原型式继承。这个方法接收两个参数:一 个用做新对象原型的对象和(可选的)一个为新对象定义额外属性的对象。在传入一个参数的状况下, Object.create()与 object()方法的行为相同。 因此上文中代码能够转变为
let cat = Cat(Animal); => let cat = Object.create(Animal);ip
核心:子类.prototype.属性=new 父类().属性内存
function Cat(name){ var animal = new Animal(); for(var p in animal){ Cat.prototype[p] = animal[p]; } Cat.prototype.name = name || 'Tom'; } // Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.sleep()); console.log(cat instanceof Animal); // false console.log(cat instanceof Cat); // true
优势:原型链
缺点:
核心:经过调用父类构造,继承父类的属性并保留传参的优势,而后经过将父类实例做为子类原型,实现函数复用(父类.call(this),子类.prototype=new 父类())
function Cat(name){ Animal.call(this); this.name = name || 'Tom'; } Cat.prototype = new Animal(); // 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
优势:
缺点:
经过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构造的时候,就不会初始化两次实例方法/属性,避免的组合继承的缺点(父类.call(this).var Super=function(){},Super.prototype=父类.prototype,子类.prototype=new Super)
function Cat(name){ Animal.call(this); //实例的方法和属性 this.name = name || 'Tom'; } (function(){ // 建立一个没有实例方法的类 var Super = function(){}; Super.prototype = Animal.prototype; //将实例做为子类的原型 Cat.prototype = new Super(); })(); // 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
优势:
缺点:
class 子类 extends 父类{constructor(){super()}}
class Cat extends Animal { constructor(name,food){ //调用父类的constructor(name) super(name); this.food = food } eat(food){ //调用父类的方法 super.eat(food); } } // 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