使用原型链
有以下代码:
function Animal(legsNumber) {
this.legsNumber = legsNumber
}
Animal.prototype.kind = '动物'
function Dog(name, age) {
this.name = name
this.age = age
}
Dog.prototype.kind = '狗'
Dog.prototype.eat = function () {
console.log(`我是${this.name},我在狂吃狂吃狂吃狂吃狂吃狂吃`);
}
var 大毛 = new Dog('大毛', 4)
大毛.eat()
上面代码包含Animal()和Dog()函数,如何让Dog()继承Animal()呢?
function Animal(legsNumber) {
this.legsNumber = legsNumber
}
Animal.prototype.kind = '动物'
function Dog(name, age) {
Animal.call(this, 4) // 关键代码1,相当于给Dog增加legsNumber属性,相当于执行了:this.legsNumber = 4
this.name = name
this.age = age
}
// 关键代码2,给Dog绑定原型,但是这句代码并不规范,不同浏览器指向原型的属性名不一样(有些浏览器用'__proto__',有些浏览器用'[[prototype]],总之并不统一'),怎么解决?
Dog.prototype.__proto__ = Animal.prototype
Dog.prototype.kind = '狗'
Dog.prototype.eat = function () {
console.log(`我是${this.name},我在狂吃狂吃狂吃狂吃狂吃狂吃`);
}
var 大毛 = new Dog('大毛', 4)
大毛.eat()
上面的代码做了以下两件事:
关键代码1: 执行Animal.call(this, 4)来给Dog绑定相关属性,增加了legsNumber属性,相当于执行了:this.legsNumber = 4;
关键代码2: 给Dog绑定原型。但是这句代码并不规范,不同浏览器指向原型的属性名不一样(有些浏览器用'proto',有些浏览器用'[[prototype]],总之并不统一'),怎么解决?
想一想解决方案:关键代码2其实是改变原型,那么如何能改变原型?有两种方法,一个是Object.create(),还有一个是new关键字,前者只能在ES6中使用,所以考虑用new关键字,可以改成:Dog.prototype = new Animal()。
但是这样子改又存在一个问题,new会返回一个带有legsNumber属性的对象(不懂原因的可以参考一下我的这篇文章:JS的new做了什么?),这样子相当于在Dog.prototype上面多了一个legsNumber属性,那么如何解决这个问题呢:
var f = function () {} //
f.prototype = Animal.prototype
Dog.prototype = new f()
上面代码相当于把Animal()的函数体改为空,这样子就避免new()的时候去绑定了不必要的参数,也就是去掉了Dog.prototype上的legsNumber。所以完整的代码:
function Animal(legsNumber) {
this.legsNumber = legsNumber
}
Animal.prototype.kind = '动物'
function Dog(name, age) {
Animal.call(this, 4) // 关键代码1,相当于给Dog增加legsNumber属性,相当于执行了:this.legsNumber = 4
this.name = name
this.age = age
}
// 关键代码2,给Dog绑定原型,但是这句代码并不规范,不同浏览器指向原型的属性名不一样(有些浏览器用'__proto__',有些浏览器用'[[prototype]],总之并不统一'),怎么解决?
// Dog.prototype.__proto__ = Animal.prototype
// 想一想解决方案:上面代码其实是改变原型,那么如何能改变原型?有两种方法,一个是Object.create(),还有一个是new关键字,前者只能在ES6中使用,所以考虑用new关键字
// Dog.prototype = new Animal()
// 上面代码又存在一个问题,new会返回一个带有legsNumber属性的对象(不懂原因的可以参考一下我的这篇文章:JS的new做了什么?),这样子相当于在Dog.prototype上面多了一个legsNumber属性,那么如何解决这个问题呢?
var f = function () {}
f.prototype = Animal.prototype
Dog.prototype = new f()
Dog.prototype.kind = '狗'
Dog.prototype.eat = function () {
console.log(`我是${this.name},我在狂吃狂吃狂吃狂吃狂吃狂吃`);
}
var 大毛 = new Dog('大毛', 4)
大毛.eat()
使用class
使用class继承可以直接使用extends关键字:
class Animal {
constructor(legsNumber) {
this.legsNumber = legsNumber
}
}
class Dog extends Animal {
constructor(name, age) {
super(4)
this.name = name
this.age = age
}
eat() {
console.log(`我是${this.name},我在狂吃狂吃狂吃狂吃狂吃狂吃`);
}
}
var 大毛 = new Dog('哮天', 5)
大毛.eat()
完。