JavaScript继承(摘抄自《JavaScript高级程序设计》)
-
原型链继承
原理:利用原型对象和原型链链来实现属性和方法的访问function Product(name) { this.name = name } Product.prototype.getName = function() { return this.name; } function Book(price) { this.price = price; } Book.prototype = new Product(); var b1 = new Book('21); b1.name = 'book'; console.log(b1.getName()) // book console.log(b1.price) // 21
缺点:
1.当存在引用类型的属性时,修改属性会影响到其它实例;
2.在实例化子类时,无法给父类传参 -
借用构造函数(经典继承)
原理:通过apply、call等调用父类的构造函数,来实现属性的继承function Product(name) { this.name = name } Product.prototype.getName = function() { return this.name; } function Book(name, price) { Product.call(this,name); this.price = price; } Book.prototype.getPrice = function() { return this.price; } var b1 = new Book('a book', 21); console.log(b1.getPrice()) // 21 console.log(b1.getName()) // TypeError: b1.getName is not a function
缺点:
1.如果需要继承方法,就必须写在父类的构造函数中,每次创建新的实例时,都会创建一遍方法,浪费资源和性能 -
组合继承(伪经典继承)
function Product(name) { this.name = name } Product.prototype.getName = function() { return this.name; } function Book(name, price) { Product.call(this,name); this.price = price; } Book.prototype = new Product(); Book.prototype.getPrice = function() { return this.price; } var b1 = new Book('a book', 21); console.log(b1.getPrice()) // 21 console.log(b1.getName()) // "a book"
优点:融合原型链继承和借用构造函数继承的优点,同时又都避免了双方的缺陷,是最常用的继承方式
缺点:会调用两次父类构造函数 -
原型式继承
原理:借助原型,并基于已有的对象,创建一个新的对象function createObj(obj) { function F() {}; F.prototype = obj; return new F(); }
缺点:实例会共享参数,同样无法避免引用类型值的问题的出现(ES5中的Object.create的模拟实现)
-
寄生式继承
原理:与原型式继承类似,创建一个仅用于封装继承的函数,同时在函数内容增强对象。function createAnther(obj) { var clone = createObj(obj); clone.sayHi = function() { console.log('hi') } return clone; }
缺点:每次新建实例,都会创建一遍方法
-
寄生组合式继承
function inheritPrototype(sub, sup) { var prototype = createObj(sup.prototype); prototype.constructor = sub; // 修改constructor指向 sub.prototype = prototype; // 修正原型链 } function Product(name) { this.name = name } Product.prototype.getName = function() { return this.name; } function Book(name, price) { Product.call(this,name); this.price = price; } inheritPrototype(Book, Product) Book.prototype.getPrice = function() { return this.price; } var b1 = new Book('a book', 21);
优点:只调用了一次父类的构造函数,且原型链保持不变