什么是对象?
对象是对于单个物体的简单抽象
对象是容器,封装了属性(对象的状态)和方法(对象的能力和行为)
面向对象、面向过程
面向对象:代码的组织方式是以对象为中心的,将数据和方法封装到对象中,通过对象之间的交互来实现程序的功能
面向过程:代码的组织方式是以过程为中心的,通过定义函数来实现程序的功能
一般我们使用面向对象编程比较多,逻辑迁移更加灵活、代码复用性更高。
简单对象
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