【笔记】JS面向对象
前言
JS面向对象学习笔记
ES6
定义类
- 类名首字母大写
1 | class 类名 { |
定义构造方法
constructor()
方法为构造方法,在创建对象时会自动执行- 构造方法不需要
function
关键字修饰 - 构造方法通过形参为对象初始化属性值
- 如果不写构造方法,类中会有默认的构造方法
- 构造方法不需要
- 必须通过
this
关键字调用当前类实例的属性或方法
1 | class 类名 { |
创建对象
- 创建对象必须在定义类之后
1 | class 类名 { |
定义方法
- 类中定义方法时不需要使用
function
关键字修饰 - 类中定义的多个方法不需要使用
,
分隔
1 | class 类名 { |
继承
- 通过
extends
关键字继承父类 - 继承父类后可以直接通过子类调用父类的属性和方法
1 | class 父类名 { |
子类调用父类方法
调用父类构造方法
- 子类通过
super()
调用父类构造方法
1 | class 父类名 { |
同时将形参传递给子类构造和父类构造
- 同时将构造方法的形参传递给子类构造方法和父类构造方法时,必须先调用父类构造方法再调用子类构造方法,
super
关键字需要在this
关键字之前
1 | class 父类名 { |
调用父类普通方法
1 | class 父类名 { |
方法的重写
- 子类重写父类同名方法
1 | class 父类名 { |
ES6之前
通过 new Object() 创建对象
1 | let 对象名 = new Object(); |
通过对象字面量创建对象
1 | let 对象名 = { |
通过构造函数创建对象
- 构造函数的函数名首字母大写
- 构造函数需要与new配合使用才有意义
- new在执行时会做的事
- 在内存中创建一个新的空对象
- 让this指向这个对象
- 执行构造函数的代码,给这个对象添加属性和方法
- 返回这个新对象,无需return关键字
1 | function 构造函数名(形参) { |
实例成员
- 通过this添加的成员属性或成员方法,实例成员只能通过实例化的对象来访问,不可以通过构造函数名直接访问实例成员
1 | function 构造函数名(形参) { |
静态成员
- 在静态函数中直接定义的属性或成员方法,只能通过构造函数名定义和访问,不能通过对象名定义和访问
1 | // 定义静态成员 |
通过原型对象实现方法的共享
- 由于每次创建对象时,其内部的方法在内存存储时都需要重新开辟空间
- 通过原型对象可以实现方法的共享,防止反复创建相同的方法
- 通过构造函数的
prototype
属性可以定义公共方法,在对象中的__proto__
属性指向了构造函数的prototype
属性,所以可以直接调用构造函数中prototype
属性定义的公共方法
1 | function 构造函数名() { |
- 原型对象(
prototype
、__proto__
)中定义了一个constructor
属性,指向了构造函数本身 - 添加多个方法时,由于会覆盖原型对象中的所有属性,所以会丢失
constructor
属性,需要重新指向构造函数- 内置构造函数不能通过对象覆盖的方式为原型对象添加多个方法
1 | 构造函数名.prototype.constructor |
原型链
- 原型链
- 通过构造函数创建的对象,包含一个
__proto__
属性,这个__proto__
属性指向了构造函数的原型对象prototype
- 构造函数的原型对象
prototype
也是一个对象,所以也有__proto__
属性,这个__proto__
属性指向了Object.prototype
- Object的原型对象
prototype
也是一个对象,所以也有__proto__
属性,这个__proto__
属性指向了null
- 通过构造函数创建的对象,包含一个
- 原型链中属性查找机制
- 首先查找这个对象自身是否有指定的属性
- 然后查找
__proto__
属性指向的原型对象中是否有指定的属性 - 然后查找
Object
的原型对象中是否有指定的属性 - 直到找到
null
为止,还没找到,返回undefined
1 | function 构造函数名() { |
- this指向
- 在构造函数中,this指向的是对象实例
- 原型对象中的this指向的是对象实例
原型对象的应用
扩展内置类方法
1 | 内置类.prototype.方法名 = function { |
继承
- 组合继承:通过构造函数+原型对象模拟继承的实现
- 通过call()函数,将子函数中的this交给父函数,作为父函数this的指向,从而实现继承属性
- 通过将子构造函数的
prototype
指向父构造函数的实例,从而实现继承父构造函数中的函数,仍然要重新修改constructor
的指向
1 | // 继承属性 |