JS继承

JS中的继承也是面试中常问的一块,常常是知其然而不知其所以然,看了视频后做一些笔记加深一下印象,以后好复习

继承

子类继承父类中的属性和方法:目的是让子类的实例能够调取父类的属性和方法

面向对象

  • 封装:低耦合高内聚

  • 多态:重载(方法名相同,形参个数或者类型不一样)与重写(在类的继承中,子类可以重写父类中的方法)

    public void sum(int n,int m){
        
    }
    public void sum(int n,int m,float x){
        
    }
    public void sum(int n,String m){
        
    }
    //后台通过重载减轻一个方法业务逻辑复杂度,减少并发
    

JS中不存在真正意义上的重载,JS中的重载指的是同一个方法,根据传参(arguments)不同,实现出不同的效果

面试问题:什么是面向对象?谈谈对它的理解

  • 面向对象是一种编程思想,JS本身就是基于面向对象构建出来的(例如JS中有很多内置类,像Promise就是ES6中新增的一个内置类,我们可以基于new Promise来创建一个实例,来管理异步编程,我在项目中,Pormise也经常用,自己也研究过它的源码…),我之前看过一点框架源码,我们平时用的vue/react/jquery也是基于面向对象构建出来的,他们都是类,平时开发的时候都是创建他们的实例来操作的,当然自己在真实项目中也封装过一些组件插件(例如dialog、拖拽…),也是基于面向对象开发的,这样可以创造不同的实例,来管理私有的属性和公有的方法,很方便…
  • JS中的面向对象,和其他编程语言还是有略微不同的,JS中类和实例是基于原型和原型链机制来处理的,而且JS中关于类的重载、重写、继承也和其他语言不太一样…

自己引申的问题:组件化与模块化

  • 组件化:把重复的代码提取出来合并成为一个个组件,组件最重要的就是重用(复用)-- 组件化开发就应用了面向对象的思想
  • 模块化:分属同一功能/业务的代码进行隔离(分装)成独立的模块,可以独立运行,独立管理,每个模块有很多接口,可供调用

原型继承

A代表父类,B代表子类

原型继承:让父类中的属性和方法在子类实例的原型链上

Child.prototype = new Parent()
Child.peototype.constructor = Child
function A(x){
    this.x = x
}
A.prototype.getX = function(){
    console.log(this.x)
}

function B(y){
    this.y = y
}
B.prototype = new A(200) //想要b1获得getX方法
B.prototype.constructor = B //保证原型重定向后的完整性
B.prototype.getY = function(){
    console.log(this.y)
}

let b1 = new B(100)//继承之前b1有y属性以及getY方法,继承之后还有x属性以及getY方法

在这里插入图片描述

特点:

  1. 不像其他语言中的继承一样(其他语言的继承一般是拷贝继承,也就是子类继承父类,会把父类中的属性和方法拷贝一份到子类中,供子类的实例调取使用),它是把父类的原型放到子类实例的原型链上,实例想要调取这些方法,是基于__proto__原型链查找机制完成

  2. 子类可以重写父类上的方法(导致父类其他的实例也受到影响)

    //举例
    B.prototype.__proto__.sum = function(){}
    
  3. 父类中私有或者公有的属性方法,最后都会变为子类中公有的属性和方法

call继承

Child方法中把Parent当作普通函数执行,让Parent中的this指向Child的实例,相当于给Child的实例设置了更多的私有的属性或者方法

function A(x){
    this.x = x
}
A.prototype.getX = function(){
    console.log(this.x)
}

function B(y){
    //==> this:B的实例b1
    A.call(this,200)
    this.y = y
}
B.prototype.getY = function(){
    console.log(this.y)
}
let b1 = new B(100)

特点:

  1. 只能继承父类私有的属性或者方法(因为是把Parent当作普通函数执行,和其原型上的属性和方法没有关系)
  2. 父类私有的变为子类私有

寄生组合继承

call继承+原生式继承

function A(x){
    this.x = x
}
A.prototype.getX = function(){
    console.log(this.x)
}

function B(y){
    //==> this:B的实例b1
    A.call(this,200)
    this.y = y
}
//Object.create(obj):创建一个空对象,让空对象__proto__指向obj
B.prototype = Object.create(A.prototype)
B.prototype.constructor = B
B.prototype.getY = function(){
    console.log(this.y)
}
let b1 = new B(100)
//Object.create的实现
Object.create = function(obj){
    function Fn(){}
    Fn.prototype = obj
    return new Fn()
}

在这里插入图片描述

ES6中的继承

ES6中基于class创造出来的类不能当作普通函数执行,所以call继承失效,也不允许重定向原型的指向

class Child extends Parent{//==> B.prototype.__proto__ = A.prototype 
    constructor(){
        super() //==> A.call(this),让方法中的this是子类的实例
    }
} 
class A{
    constructor(x){
        this.x = x //私有属性
    }
    getX(){
        console.log(this.x) //原型链上的方法
    }
   // A.prototype.x = xx //在原型链上添加属性
}

class B extends A{
    constructor(y){
        super(200)//子类继承父类,可以不写constructor(浏览器会自己默认创建=> constructor(...args){super(...args)}),一旦写了,则在constructor中的第一句话必须是super()
        this.y = y //私有属性
    }
    getY(){
        console.log(this.y) //原型链上的方法
    }
}
let b1 = new B(100)

应用

class Utils{
    query(){}
}
class Dialog extends utils{
    constructor(){
        super()
        this.query()
    }
}

new B(100)


# 应用

```js
class Utils{
    query(){}
}
class Dialog extends utils{
    constructor(){
        super()
        this.query()
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值