面向对象
面向过程-面向对象-面向组件-面向模块
对象:包含属性和方法
对象生成
简单对象-共享
const obj = {
name: 'gpf',
age: 27,
getPro: function(newPro){
return newPro
}
}
// 该对象是引用,修改会引起其他引用处的变化
构造函数生成对象
-
函数体内生成的this指向创建的实例
-
生成实例需要使用new进行实例化
-
可以做初始化传参
function Course(){ this.teacher = 'yunyin' this.leader = 'xiaowen' this.startCourse = function(name){ return name } } // js对象不基于类,基于构造函数+原型链 // 生成新对象实例,实例之间不互相影响 const course = new Course('yunyin')
new的时候做了什么
- 创建空对象,作为返回的对象实例
- 将空对象的原型对象设置为构造函数的 prototype
- 将当前实例对象设置给内部的this
- 执行构造函数的初始化代码
重新构造一遍:不互相影响
构造函数执行没有意义,其中的this为window,想要使用 const course = Course()构造对象可以采用检测返回的方式
function Course(){
// 未实例化this指向window,实例化之后this指向当前实例
const _isClass = this instanceof Course
if(!_isClass){
return new Course()
}
this.teacher = 'yunyin'
this.leader = 'xiaowen'
this.startCourse = function(name){
return name
}
}
constructor是什么
- 构造器,每个对象创建时都会有
- 继承自原型对象,指向构造函数的引用
构造函数继承属性会有什么性能上的问题
// 构造函数中的方法会存在于每个实例,但方法往往不需要重复创建
const course1 = new Course('this')
const course2 = new Course('OOP')
course1.startCourse 与 course2.startCourse 重复占用空间
构造函数的prototype === 实例的__proto__属性 相同的内存堆
course1.constructor === Course
解决方法:挂在共享的原型对象
Course.prototype.startCourse = function(name){
return name
}
原型链:共用原型地址,节省内存
实例的__proto__的__proto__为父级的prototype
course1.__proto__.__proto__ === Object.prototype
Object.prototype.__proto__ = null
因此Course可以使用Object的hasOwnProperty方法
另外,Course.__proto__ === Function.prototype
js实现继承
使用原型链继承父类方法
function Game(){
this.name = 'Game'
this.skin = ['s']
}
Game.prototype.getName = function(){
return this.name
}
function LOL(){}
LOL.prototype = new Game() // 直接把父类生成的实例挂在原型上
LOL.prototype.constructor = LOL
const lol1 = new LOL();
const lol2 = new LOL();
lol1.skin.push('ss')
能实现继承,但两者由于原型共享而互相影响,无法分离,且无法初始化传参
// 解决方法:组合继承
function LOL(arg){
Game.call(this, arg)
}
LOL.prototype = new Game() // 直接把父类生成的实例挂在原型上
LOL.prototype.constructor = LOL
const lol3 = new LOL('lol3')
问题父类构造函数被执行两次 Game.call、new Game,且若有计数则计算错误
// 解决方法:寄生组合继承
function LOL(arg){
Game.call(this, arg)
}
LOL.prototype = Object.create(Game.prototype)
LOL.prototype.constructor = LOL
多重继承
function LOL(arg){
Game.call(this, arg)
Store.call(this, arg)
}
LOL.prototype = Object.create(Game.prototype)
Object.assign(LOL.prototype, Store.prototype)
LOL.prototype.constructor = LOL