面向对象/原型及原型链

对象

为什么要面向对象?

面向对象(OOP)特点:

  • 逻辑迁移灵活
  • 代码可复用性高
  • 高度模块化
对象的理解

对象是什么?

  • 对象是对单个物体的简单抽象
  • 对象是一个容器,封装了属性&方法
    1.属性:对象的状态
    2.方法:对象的行为
// 简单对象
const Course = {
	teacher: 'xx',
	leader: 'yy',
	startCourse: function (name) {
		return `开始${name}`
	}
}
// 函数对象 (JS中通常使用函数对象)
function Course () {
	this.teacher = 'xx'
	thie.leader = 'yy'
	this.startCourse = function (name) {
		return `开始${name}`
	}
}

构造函数

  • 构造函数的功能 — 生成对象
  • 需要一个末班 — 表征了一个物体的共同特征,从而生成对象
  • 类即对象模板
  • JS本质上不是基于类。而是基于构造函数 + 原型链
  • constructor + prototype
function Course () {
	this.teacher = 'xx'
	thie.leader = 'yy'
}
const course = new Course()

Course 本质就是构造函数

  1. 函数体内是用的this,代表所要生成的实例
  2. 生成对象通过new来实例化
  3. 可以做初始化传参
new

构造函数通过new方法生成实例

function Course () {}
const course = new Course()
 console.log(Course.prototype === course.__proto__)  // true
  1. 创建了一个空对象,作为返回的对象实例
  2. 将生成的空对象的原型对象指向了构造函数的prototype属性
  3. 将当前实例对象赋给了内部的this
  4. 执行构造函数初始化代码

在这里插入图片描述

constructor
  • 每个对象创建时会自动拥有一个构造函数属性constructor
  • constructor 继承自原型对象,指向构造函数的引用
function Course (teacher, leader) {
	this.teacher = teacher
	this.leader = leader
}
const course = new Course('xx', 'yy')

console.log(course.constructor === Course)  // true
// 生成实例的 constructor  就是构造函数 Course
// 构造函数 Course 的 prototype 是 constructor  
注:构造函数是用来描述一个物体的, 构造函数通过new方法生成一个实例 实例拥有 proto 实例的__proto__ 指向构造函数的 prototype 对象创建时会拥有构造函数属性 constructor 继承自原型对象 指向构造函数引用

原型对象 Course.prototype

让挂载 prototype 上的属性、方法 所有实例都可以公用

function Course () {}
Course.prototype.teacher = 'xx'
const course1 = new Course()
const course2 = new Course()
console.log(course1.teacher) // 'xx'
console.log(course2.teacher) // 'xx'

// 对构造函数中的方法 重复挂载导致资源浪费 的 优化
Course.prototype.startCourse = function (name) {
	return `开始${name}`
}
console.log(course1.startCourse('ES6')) // 开始ES6课
console.log(course2.startCourse('OOP')) // 开始OOP课
构造函数、实例对象、原型对象 总结:
function Course () {}
const course = new Course()
  • 构造函数:用来初始化创建对象的函数, — Course

     1.1.自动给构造函数赋予一个属性 prototype  ,该属性实际等于实例对象的原型对象
    
  • 实例对象:course 就是实例对象,根据原型创建出来的实例

     2.1.每个对象中都有一个__proto__,
     2.2.每个实例对象都有一个 constructor 属性, 
     2.3.constructor 由继承而来,并指向当前构造函数
    
  • 原型对象:Course.prototype
    在这里插入图片描述

继承

继承:在原型对象的所有属性和方法,都能被实例所共享

继承一:原型链继承 (子类 的 prototype 指向父类的实例)
// Game 类
function Game () {
	this.name = 'try'
}
Game.prototype.getName = function () {
	retrun this.name
}

// LOL 类
function LOL () {}
//  LOL 继承 Game
LOL.prototype = new Game()
LOL.prototype.constructor  = LOL
const game = new LOL()
// 本质:重写原型对象,将父对象的属性方法,作为子对象原型对象的属性和方法

在这里插入图片描述
原型链继承缺点:

  1. 父类属性一旦赋值给子类对的原型属性,此时属性属于子类的共享属性
  2. 实例化子类的时候,不能向父类传参
继承二:构造函数继承 / 经典继承 (在子类构造函数内部调用父类构造函数)
// Game 类
function Game (arg) {
	this.name = 'try'
	this.skin = ['skin']
}
Game.prototype.getName = function () {
	retrun this.name
}
// LOL 类
function LOL (arg) {
	Game.call(this, arg) // 实例化子类的时候向父类传参
}
//  LOL 继承 Game
const game1 = new LOL()
const game2 = new LOL()
game1.skin.push('ww') // game1 不影响 game2
// 解决了共享属性问题 和 传参问题

构造函数缺点:原型链上的共享方法无法被读取继承

继承三:组合继承
// Game 类
function Game (arg) {
	this.name = 'try'
	this.skin = ['skin']
}
Game.prototype.getName = function () {
	retrun this.name
}

// LOL 类
function LOL (arg) {
	Game.call(this, arg)
}

//  LOL 继承 Game
LOL.prototype = new Game()
LOL.prototype.constructor  = LOL
const game = new LOL()

组合继承缺点:如论何种场景,都会调用两次父类构造函数

  1. 初始化子类原型时
  2. 子类构造函数内部 call 父类的时候
继承四:寄生组合继承
// Game 类
function Game (arg) {
	this.name = 'try'
	this.skin = ['skin']
}
Game.prototype.getName = function () {
	retrun this.name
}

// LOL 类
function LOL (arg) {
	Game.call(this, arg)
}

//  LOL 继承 Game
LOL.prototype = Object.create(Game.prototype)
LOL.prototype.constructor  = LOL
const game = new LOL()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值