JS的面向对象、原型及原型链

文章介绍了JavaScript中的对象概念,包括对象作为容器封装属性和方法的特性,以及面向对象编程与面向过程编程的区别。接着,详细讲解了简单的对象、函数对象、构造函数以及new操作符的工作原理。还讨论了原型、原型链和不同类型的继承方式,如原型链继承、构造函数继承、组合继承及寄生组合继承,以及它们各自的优缺点。最后提到了多重继承的概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么是对象?
对象是对于单个物体的简单抽象
对象是容器,封装了属性(对象的状态)和方法(对象的能力和行为)

面向对象、面向过程
面向对象:代码的组织方式是以对象为中心的,将数据和方法封装到对象中,通过对象之间的交互来实现程序的功能
面向过程:代码的组织方式是以过程为中心的,通过定义函数来实现程序的功能
一般我们使用面向对象编程比较多,逻辑迁移更加灵活、代码复用性更高。

简单对象

let Game = {
	name: 'LOL',
	getName: function(){
		return this.name
	}
}
Game.name = "原神"
Game.getName() //原神

缺点:对象中的属性会被改变,需要用到初始值时会有问题。

函数对象

function Game(name){
	this.name = name
	this.getGame = function (){
		return this.name
	}
}
//可以彼此隔离

构造函数 - 就是js中生成的对象 => 实例
需要一个模版 - 一类物体具有共同特性,从而生成对象
类即对象模版(js通过构造函数和原型链实现类)

function Game(name){
	this.name = name
	this.getGame = function (){
		return this.name
	}
}
const g1 = new Game('第五人格')
g1.getGame() //第五人格

Game本质上就是构造函数
1.函数体内使用的this,指向所要生成的实例
2.生成对象用new来实例化
3.可以初始化传参

new的原理
1.结构上:创建了一个空对象,作为返回的对象实例
2.属性上:将生成空对象的原型对象指向了构造函数的prototype属性
3.关系上:将当前实例对象赋值给了内部的this
4.生命周期上:执行了构造函数的初始化代码

function _new(obj,...args){
	// 基于obj的原型创建一个新的对象
	const newObj = Object.create(obj.prototype)
	//添加属性到新创建的newObj上, 并获取obj函数执行的结果
	const result = newObj.apply(obj,args)
	//如果执行结果有返回值并且是一个对象, 返回执行的结果, 否则, 返回新创建的对象
	return typeof result === 'object' ? result : newObj
}

如果在项目中使用,且不希望外界感知,如何拿到实例化的对象?
单例模式:可以使外界拿到实例化后的对象

function Game(name){
	const _isGame =  this instanceof Game
	if(!_isGame)  return new Game()
	this.name = name
	this.getGame = function (){
		return this.name
	}
}
let g1 = Game()
let g2 = new Game()

constructor是什么?
1.每个对象在创建时,会自动拥有一个构造函数属性constructor
2.constructor来自原型对象,指向了构造函数的引用

console.log(g1.__proto__.constructor == Game); //true

原型、原型链
原型:每个实例化的对象上都有一个__proto__的属性,这个属性指向构造函数的prototype
原型链:构造函数同样也有__proto__属性,它指向上层的prototype,直到指向为null,会形成一条链就是原型链

console.log(g1.__proto__ == Game.prototype); //true
console.log(g1.__proto__. __proto__== Object .prototype); //true
console.log(Game.prototype. __proto__== Object .prototype); //true
console.log(g1.__proto__. __proto__. __proto__== null); //true

原型链继承

function Game(){
	this.name = 'LOL'
}
Game.prototype.getGame = function(){
	return this.name
}
function DaoTa(){}
DaoTa.prototype = new Game()
DaoTa.prototype.constructor = DaoTa
const d1 = new DaoTa()
d1.getGame() //LOL

缺点:1. 父类属性一旦赋值给到子类的原型属性,此时属性属于子类的共享属性了
2. 实例化子类时,无法向父类进行传参

构造函数继承:在子类的构造函数调用父类的构造函数

function Game(name){
	this.name = name
}
Game.prototype.getGame = function(){
	return this.name
}
function DaoTa(arg){
	Game.call(this,arg)
}
const d1 = new DaoTa('LOL')
d1.getGame() //TypeError: d1.getGame is not a function

缺点:原型链上的共享方法无法继承

组合继承

function Game(name){
	this.name = name
}
Game.prototype.getGame = function(){
	return this.name
}
function DaoTa(arg){
	Game.call(this,arg)
}
DaoTa.prototype = new Game()
DaoTa.prototype.constructor = DaoTa

缺点:会调用两次父类的构造函数

寄生组合继承

function Game(name){
	this.name = name
}
Game.prototype.getGame = function(){
	return this.name
}
function DaoTa(arg){
	Game.call(this,arg)
}
DaoTa.prototype = Object.create(Car.prototype)
DaoTa.prototype.constructor = DaoTa

多重继承

function Game(name){
	this.name = name
}
Game.prototype.getGame = function(){
	return this.name
}
function Shop(){
	this.name = 'App Store'
}
Shop.prototype.getGame = function(){
	return this.name
}
function LOL(name){
	Game.call(this,name)
	Shop.call(this)
}
LOL.prototype = Object.create(Game.prototype)
Object.assign(LOL.prototype,Shop.prototype)
LOL.prototype.constructor = LOL
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值