浅谈 JS 中继承的写法
2019-10-10 本文已影响0人
_ClariS_
JS中的几种流派
继承是属于面向对象流派
什么是类
定义:能产生对象的东西即为“类”
举个例子
这里的 Human 就是一个类
什么是继承
定义:继承就是描述类和类之间的关系,它可以使得子类别具有父类别的各种属性和方法
上面的例子中,Human的部分属性继承自Object,这是所有对象都存在的一个自带的继承关系。而Man继承自Human,这是我们自己实现的一个继承关系。
image.png这里要特别注意实例属性与继承的区别
实例属性与继承的区别从上图中可以看出,继承的实质就是进行两次的原型搜索
另外,只有构造函数有prototype属性,prototype属性只有一个功能就是存放共有属性对象
的地址
ES5实现继承的写法
如何实现下图中的继承关系
image.png image.png这两句代码就实现了上图中的继承关系。但是__proto__
不是一个标准属性,因此不能直接写 Man.prototype.__proto__ = Human.prototype
,我们可以通过 new 来间接操作__proto__
但是 Human 中有this.name = name
function Human(name){
this.name = name
}
直接写为Man.prototype = new Human()
的话,由于 new 内的第④个步骤,会执行Human.call(),会出现我们不需要的结果。
你说把this.name = name
删掉就可以了呀,但这样又会破坏原本的父类Human中的结构,于是我们就陷入了想删又不能删的境地。
解决方法:
我们可以用下面三句代码来代替
var f = function(){} // 声明一个空函数f
f.prototype = Human.prototype // 让这个空函数f的原型指向Human的原型
Man.prototype = new f() // Man.prototype.__proto__ = f.prototype
这三句代码的作用就是让 Man.prototype.__proto = Human.prototype
,且解决了上面的问题
于是,最终完整版代码如下
function Human(name){
this.name = name
}
Human.prototype.run = function(){
console.log("我叫"+this.name+",我在跑")
return undefined
}
function Man(name){
// 这里的this指向Man实例,将Man实例和name作为参数传入构造函数Human中
Human.call(this, name)
this.gender = '男'
}
/*Man.prototype.__proto__ = Human.prototype*/
var f = function(){}
f.prototype = Human.prototype
Man.prototype = new f()
Man.prototype.fight = function(){
console.log('糊你熊脸')
}
ES6实现继承的写法
对比ES5的写法,ES6的写法就很容易理解了
class Human{
constructor(name){ // 自身属性写到constructor中
this.name = name
}
run(){ // 原型上的属性就直接写在Human这个类中
console.log("我叫"+this.name+",我在跑")
return undefined
}
}
// Man extends Human 等价于 Man.prototype.__proto = Human.prototype,也相当于上面的三句代码
class Man extends Human{
constructor(name){
super(name) // 相当于Human.call(this, name)
this.gender = '男'
}
fight(){
console.log('糊你熊脸')
}
}
那如果想在原型上声明一个非函数如何做到呢?
ES5的写法:
function Human(name){
this.name = name
}
Human.prototype.种族 = '人类'
Human.prototype.run = function(){
console.log("我叫"+this.name+",我在跑")
return undefined
}
ES6的写法:
class Human{
constructor(name){ // 自身属性写到constructor中
this.name = name
}
get 种族(){
return '人类'
}
run(){ // 原型上的属性就直接写在这个类中
console.log("我叫"+this.name+",我在跑")
return undefined
}
}