面向对象
什么是对象,面向对象的优势
JS是脚本化语言,一行一行执行,一边运行一边解析,过程化语言;
面向对象:将开发内容独立化拆分出一个主体,对主体进行逻辑设计
例如上课
过程:上课:start(开始上课)- ask(询问) - before(回顾)- main(课内容)- over(完成)
面向对象: 以课程为主体,课程有上面这些方法;以这个对象为基础,可以生成多个课程实例,
对象的理解
- 对象是对单个物体的简单抽象
- 对象是基础/模板,对象也是容器,可以存放属性,方法,上面的过程 变为 对对象属性和方法的填充
对象的优势
-
逻辑迁移更灵活,不需要去修改每个实例,只需要去修改对象模板;
-
代码复用性高,
-
高度模块化
function Course() { this.teacher = 'yy' this.class = 'oop' this.startCourse = function(name) { return `开始${name}课程` } // ……初始化 } const course1 = new Course() // 构造实例的函数对象 => 构造函数 => 严谨化构造一个对象
构造函数 - 生成对象,相当于对象模板
js对象本质 基于构造函数 + 原型链的传递方式
问:实例化生成对象之间的关系
对象彼此之间是独立的
问:constructor存在的意义 - 构造一类
- 每个实例对象被创建,会自动拥有一个证明身份的属性,constructor
- constructor来自于原型对象,指向构造函数的引用
问:使用构造函数创建对象有什么问题
当属性是方法时,每次都会创建一个新函数,造成资源浪费 => 函数放在原型上 Course.prototype.startCourse = function(){...}
原型对象
course1__proto__ = Course.prototype;
Course.prototype,相当于父类的属性和方法 实例对象可以通过原型对象,course1.__proto__访问
生成的实例对象对应__proto__属性;构造函数对应prototype属性
Course()一方面是构造函数,所以course1__proto__ = Course.prototype;
Course()同时也是一个函数,是一个函数对象的实例,所以Course__proto__ = Function.prototype;
Object()同上,是一个构造函数,也是一个函数对象 Object__proto__ = Function.prototype;
继承
1.重写原型,原型对象中的属性和方法都可以被继承(可以调用)
function Game () {
this.name = 'LOL';
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');
lol2.skin = ['s','ss'];
重写原型缺点
- 父类属性 赋值给 子类原型属性,就变成子类实例共享了,一旦修改都会有影响
- 实例化时,无法向父类传参
2.构造函数继承(借助call)解决共享属性+传参问题
function Game () {
this.name = 'LOL'
this.skin = ['s']
}
function LOL(arg) {
Game.call(this, arg)
}
const lol1 = new LOL()
const lol2 = new LOL()
lol1.skin.push('ss')
构造函数继承问题
原型链上的方法无法读取继承
3.组合继承(前两种组合)
function LOL(arg) {
Game.call(this, arg)
}
LOL.prototype = new Game();
LOL.prototype.constructor = LOL;
组合继承问题,父类构造函数会被执行两次
4.原型式继承
有一个对象作为基础,不用创建构造函数
let parent = {
name: 'parent',
friends:['aa','bb'],
getName: function(){...}
}
let child = Object.create(parent)
5.寄生组合继承
function LOL(arg) {
Game.call(this, arg)
}
LOL.prototype = Object.create(Game.prototype);
LOL.prototype.constructor = LOL;
如何实现一个私有变量?
对象->独立的模块;闭包->可以引用内部作用域
==> 既可以隔离,又有和外部关联的桥梁
function createStack() {
// 独立作用域
const items = []
return {
push(item) {
items.push(item)
}
setItem() {}
getItem() {
return items
}
}
}