前言
本文默认读者对于JavaScript原型链
,面向对象编程OOP
有一定的了解
JS中没有类class的概念,也没有继承的概念,这里使用这些术语只是为了方便理解JS面向对象编程的方式
ES5的JS继承模型
//基类
function Animal(name, energy) {
this.name = name
this.energy = energy
}
Animal.prototype.eat = function (amount) {
console.log(`${this.name} is eating.`)
this.energy += amount
}
Animal.prototype.sleep = function (length) {
console.log(`${this.name} is sleeping.`)
this.energy += length
}
Animal.prototype.play = function (length) {
console.log(`${this.name} is playing.`)
this.energy -= length
}
复制代码
//子类
function Dog(name, energy, breed) {
Animal.call(this, name, energy)
this.breed = breed
}
Dog.prototype = Object.create(Animal.prototype)
Dog.prototype.constructor = Dog
Dog.prototype.bark = function () {
console.log('Woof Woof!')
this.energy -= 1
}
复制代码
ES5中实现继承的几个关键操作:
-
子类构造函数中调用父类的构造函数,实现部分属性构造
Animal.call(this, name, energy)
操作本质在于:对于子类实例调用父类的构造函数,但是
this
关键字的指向是子类的实例,而不是父类实例 -
子类的原型对象指向父类
Dog.prototype = Object.create(Animal.prototype)
子类的原型是父类的一个实例对象,因此原型链的查找原则对于子类适用
-
子类的构造函数指向子类自身的构造函数
Dog.prototype.constructor = Dog
由于上面第二步的操作,导致子类原型对象(也就是父类的一个实例对象)的
constructor
属性是父类的构造函数,因此需要手动将其设置为子类自身原来的构造函数
ES6中原型与继承
ES6中JS可以使用class关键字,但是只是语法糖(syntax sugar)而已,本质上原型链方式并没有改变
//父类
class Animal{
constructor(name,energy){
this.name=name
this.energy=energy
}
eat (amount) {
console.log(`${this.name} is eating.`)
this.energy += amount
}
sleep(length) {
console.log(`${this.name} is sleeping.`)
this.energy += length
}
play(length) {
console.log(`${this.name} is playing.`)
this.energy -= length
}
}
//子类
class Dog extends Animal{
constructor(name,energy,breed){
super(name,energy)
this.breed=breed
}
bark() {
console.log('Woof Woof!')
this.energy -= 1
}
}
复制代码
作为JS原语言使用者的一些感想
JavaScript是一门多范式编程语言,可以是 函数式编程
,面向对象编程
,面向过程编程
...
这里的范式指代编程中的一些原则:
- js中函数也是一种数据类型,因此可以实现函数式编程方式
- 如同本文讲述的JS继承语法问题,这让JS可以实现面向对象编程的方式
。。。。。。
本质而言,这些都是语法层面上为熟悉OOP编程
或者FP编程
开发者减少开发时间成本
我个人对JS语言感觉就是,这门语言真的很混乱,从语言标准ES到语言实现JS存在这很大的差距,不仅是语法上的差距,还有实现原理上的差距,幸运的是我们有 babel
JS
所以个人看法就是:熟悉JS基本原理 + 学习ES最新语法 + babel转码
有反驳的欢迎来锤