简单理解下JavaScript中的继承
我们为什么需要继承,打个比方,小明的爸爸有100万财产,这是小明打一辈子工也得不到的, 但是如果小明能够继承爸爸的100W财产,那么小明就很容易就获得了100W的财产, 都不用去打工了.
同样的再js中,父对象中有一些类或者方法, 如果别的对象(子对象)也想用, 又不能偷不能抢,那么久需要通过某种方式来继承父对象中的一些方法. 在js中有几种方法,下面会提及,但可能不全,想知道更全面的自己查文档.
1.原型继承
顾名思义就是通过原型来实现继承,我我们都知道,每个函数都会有一个 prototype 属性,叫做函数的原型,每个对象也会有一个 __ proto__ 属性,它指向的也就是函数的原型.上案例.
function Father() {
this.money = '100万'
this.height = '180CM'
}
// 同时在Father的原型上定义一些方法
Father.prototype.run = function() {
console.log('坐游艇');
}
function Son() {
}
var son =new Son()
console.log(son.money);//undefined
这时候如果答应son.money,会发现,啥也没有,因为还没继承,不应该就有.
下面开始继承.我们都知道js的查找规则,比如当在自身找不到该money属性时,就会去它的原型上找,原型上没有,继续去原型的原型上找,直到一直找到null为止(查找方法也是这样)
Son 就像是实例对象 son 的妈妈,儿子找不到东西,new Father() 就相当于别人的爹
function Father() {
this.money = '100万'
this.height = '180CM'
}
// 同时在Father的原型上定义一些方法
Father.prototype.run = function() {
console.log('坐游艇');
}
function Son() {
}
var son =new Son()
son.__proto__ = new Father()
console.log(son.money); // 100万
son.proto = new Father() 这句话一做完,就相当于儿子自己找了个 干爹有100W并且继承了,但是这样子做不太好,那假如还有二儿子(实例对象)son2呢?那son2 想要100W,又得找个干爹
function Father() {
this.money = '100万'
this.height = '180CM'
}
// 同时在Father的原型上定义一些方法
Father.prototype.run = function() {
console.log('坐游艇');
}
function Son() {
}
var son =new Son()
son.__proto__ = new Father()
console.log(son.money); // 100万
var son2 = new Son()
console.log(son2.money); // undefined 显然二儿子没有100万
那么Son 妈妈为了打局考虑,直接把有100万的new Father() 讨来当老公了,那么以后的儿子**(实例对象)**就都有100万了,如下
function Father() {
this.money = '100万'
this.height = '180CM'
}
// 同时在Father的原型上定义一些方法
Father.prototype.run = function() {
console.log('坐游艇');
}
function Son() {
}
Son.prototype = new Father()//这句就重点
var son =new Son()
console.log(son.money); // 100万
var son2 = new Son()
console.log(son2.money); // 100万
son2.run() //坐游艇
这样子就两全其美,都有100万了.
但是如果要传参数呢?
function Father(ceo) {
this.money = '100万'
this.height = '180CM'
this.ceo = ceo
}
// 同时在Father的原型上定义一些方法
Father.prototype.run = function() {
console.log('坐游艇');
}
function Son() {
}
Son.prototype = new Father('麻花藤')
var son =new Son()
console.log(son.money,son.height,son.ceo); // 100万
var son2 = new Son()
console.log(son2.money,son2.height,son2.ceo); // 100万
son2.run()
这样子就显得不太好不是每个儿子都想当麻花藤,结果就这样子被安排了,肯定也不开性,这也是原型继承的其中一个不好的地方,也就是传参数并不方便/不好
2.借用继承
其实就是利用了apply() ,call() ,这两个函数也叫借用函数,具有改变一些方法内部的this指向的作用. 同样的案例,儿子想要100万
function Father() {
this.money = '100万'
this.height = '180CM'
}
// 同时在Father的原型上定义一些方法
Father.prototype.run = function() {
console.log('坐游艇');
}
function Son() {
// 这个 this 指向的将是Son的实力对象
Father.call(this) //这句话就是调用了构造函数Father,并把this指向,指向了Son的实例对象
// 等价于
// this.money = '100万'
// this.height = '180CM'
// 从此就有了Father里面的属性
}
var son =new Son()
console.log(son.money,son.height); // 100万
var son2 = new Son()
console.log(son2.money,son2.height); // 100万
son2.run()
但是这样子继承并不好,就是实力对象son 并不能使用构造函数Father 上的方法,原因很简单,因为Father.call(this) 仅仅相当一执行了Father里面的两句函数this.money = '100万' this.height = '180CM'
,而方法实在Father 的原型上,所以没有继承过来,这也是借用继承的一个弊端.
3.组合继承
既然原型继承传参不方便不好处理,而借用继承又不能继承父函数原型上的方法,那么我们想,要是把两种继承结合起来使用,那是不是传参数,继承原型方法就都没问题了呢?说干就干,我们试一下[组合继承]看代码
function Father(zhiwei) {
this.money = '100万'
this.height = '180CM'
this.zhiwei = zhiwei
}
// 同时在Father的原型上定义一些方法
Father.prototype.run = function(name) {
console.log('我是'+name+',我在坐游艇');
}
function Son(zhiwei) {
Father.call(this,zhiwei)
// Father.apply(this,[zhiwei])
}
Son.prototype = new Father()
var son =new Son('乞丐')
console.log(son.money,son.height,son.zhiwei); // 100万
var son2 = new Son('总经理')
console.log(son2.money,son2.height,son2.zhiwei); // 100万
son.run('大儿子')
son2.run('二儿子')
可见,如果使用 组合继承(原型继承+借用继承) ,就可以很好的解决上面提到的小缺陷.
4.类的继承
类是es6 语法中才出现的,也是较为复合其他编程语言的,被大多数人所能接受, 开门见山, 我们直接说,类是如何进行继承的语法: class 子类 extends 父类 {}
// 定义一个父类
class Father {
constructor(){
this.money = '100万'
this.car = '劳斯莱斯'
}
}
var f = new Father()
console.log(f.money,f.car);
// 定义一个子类
class Son extends Father{
}
var son = new Son()
console.log(son.money,son.car);
每个类里面都有一个构造函数constrouct(){} ,这个方法在一旦进行new 的时候就直接地调用了,毫不例外,在子类中也有这样的方法.但是要注意,如果,子类有继承,且写了constrouct方法,那么在里面的最前面一定要先调用super()方法,也就是下面这样.于是,子类也可以初始化自己的一些属性了.
constructor(meinv){
super()
}
// 定义一个父类
class Father {
constructor(){
this.money = '100万'
this.car = '劳斯莱斯'
}
run(methos) {
console.log('我在'+ methos);
}
}
var f = new Father()
console.log(f.money,f.car);
// 定义一个子类
class Son extends Father{
constructor(meinv){
super()
this.meinv = meinv
}
}
var son = new Son('奶茶妹')
console.log(son.money,son.car,son.meinv);
son.run('游泳')
这样子,子类即实现了继承父亲的属性,也初始化了自己的属性(奶茶妹),还能有父亲的方法run,真是各种美滋滋.
JavaScript中的继承就讲到这里,网上有很多各种继承,我也没有深究,想了解更多的可以去看MDN官方文档. 前端小白写文,难免与错漏,望指出与更正
本文地址:https://blog.csdn.net/weixin_43314255/article/details/114261750
上一篇: MySQL主从复制断开的常用修复方法
下一篇: javascript中BOM对象(二)