javascript——原型与继承
一、什么是继承?
继承是面向对象语言的一个重要概念。许多面向对象语言都支持两种继承方式:接口继承和实现继承;接口继承只继承方法签名,而实现继承则继承实际的方法。由于函数没有签名,所以ECMAScript只支持实现继承,而实现继承主要是依靠原型链来实现的。
二、继承的多种方法分析
(一)原型继承
基本思想:利用原型让一个引用类型继承另一个引用类型的属性和方法;
1 function Animal() { 2 this.species = '动物' 3 this.colors = ['白色'] 4 } 5 function Cat(name, eat) { 6 this.name = name 7 this.eat = eat 8 } 9 Cat.prototype = new Animal() 10 var cat1 = new Cat('猫', '老鼠') 11 console.log(cat1.species) //动物 12 console.log(cat1.colors) //['白色']
存在的问题:
cat1.colors.push('黑色') cat1.colors //['白色', '黑色'] cat2.colors //['白色', '黑色']
当tCat通过原型链继承了Animal后,Cat.prototype就变成了Animal的一个实例,因此它也拥有了一个自己的colors属性,结果:Cat的所有的实例都会共享colors属性;
(二)构造函数继承
基本思想:在子类型构造函数的内部调用超类型构造函数。函数只不过是在特定环境中执行代码的对象,因此可通过使用call()和apply()在新创建的对象上执行构造函数
1 function Cat(name, eat) { 2 3 Animal.apply(this, arguments) 4 this.name = name 5 6 this.eat = eat 7 8 } 9 10 var cat1 = new Cat('猫', '鱼') 11 12 console.log(cat1.species) //动物 13 cat1.colors.push('黑色') 14 console.log(cat1.colors) //['白色', '黑色'] 15 var cat2 = new Cat('猫', '猫粮') 16 console.log(cat2.colors) //['白色']
存在问题:方法都在构造函数中定义,所以没法利用函数的复用;并且在超类型的原型中定义的方法对于子类型而言是不可见的。
function Animal() { this.species = '动物' this.colors = ['白色'] } Animal.prototype.getColor = function() { return this.colors } function Cat(name, eat) { Animal.apply(this, arguments) this.name = name this.eat = eat } var cat1 = new Cat('猫', '鱼') cat1.getColor() //报错:cat1.getColor is not a function
(三)组合继承
基本思想:使用原型链实现对原型属性和方法的继承,而通过构造函数实现对实例属性的继承;
function Animal(species) { this.species = species this.colors = ['白色'] } Animal.prototype.getColor = function() { console.log(this.colors) } function Cat(name, eat) { //继承属性 this.name = name this.eat = eat Animal.call(this, name) } //继承方法 Cat.prototype = new Animal() Cat.prototype.concatructor = Cat Cat.prototype.sayName = function() { console.log(this.name) } var cat1 = new Cat('猫', '吃鱼') cat1.colors.push('黑色') console.log(cat1.colors) //['白色', '黑色'] cat1.getColor() //['白色', '黑色'] cat1.sayName() //'猫' var cat2 = new Cat('波斯猫', '吃猫粮') console.log(cat2.colors) //['白色'] cat2.getColor() //['白色'] cat2.sayName() //'波斯猫'