1. 什么是面向对象 2. 封装 3. 继承 4. 多态
一. 什么是面向对象:
1. 什么是面向对象: 程序中,都是先用对象结构,集中保存一个事物的属性和功能,然后再按需使用事物的属性和功能
2. 什么是对象: 程序中,集中存储现实中一个事物的属性和功能的程序结构/存储空间
3. 为什么: 便于大量数据的管理和维护
4. 何时: 今后,所有项目都是用面向对象思想做的
5. 如何: 面向对象三大特点: 封装,继承,多态
二. 封装:
1. 什么是: 创建一个对象,集中保存一个事物的属性和功能
2. 为什么: 为了便于大量数据的管理和使用
3. 何时: 今后只要使用面向对象方式编程,都必须先创建所需的对象,再按需调用对象中的属性和方法
4. 如何创建对象: 3种:
(1). 用{}创建一个对象:
a. var 对象名={
属性名: 属性值,
... : ... ,
方法名: function(){
... this.属性名 ...
},
方法名: function(){
... this.属性名 ...
}
}
b. 何时: 如果在创建对象时,已经知道对象的成员内容
(2). 用new Object()创建:
a. 2步:
1). 先创建一个空对象: var 对象名=new Object()
其中: new Object()可简写为{}
2). 向空对象中强行添加新属性和方法:
对象名.属性名=值
对象名.方法名=function(){
... this.属性名 ...
}
b. 何时: 当创建对象时,暂时不知道对象中的成员,就可先创建空对象,稍后得知对象的成员内容后,再强行添加进对象中。
c. 揭示: js中一切对象低层都是关联数组:
1). 长得像: 都是名值对儿结构!
2). 都可用["属性名"]和.属性名两种方式访问成员!
对象.属性名是对象["属性名"]的简写
对象.属性名也会被自动翻译为对象["属性名"]
a. 如果属性名是已知的固定的名字,两者都可用!
b. 但是如果属性名来自于一个可能变化的变量!则只能用[变量],且不能加"",因为变量一旦放入""中,就成了写死的字符串,无法改变了。
3). 访问不存在的属性,都不会报错!而是返回undefined!
用途: 判断对象中是否已经包含某个属性!
对象.属性名===undefined 说明对象中不存在该属性
对象.属性名!==undefined 说明对象中存在该属性
4). 强行给不存在的属性或位置赋值,也不会报错!而是在该新位置自动添加新属性。
用途: 今后向对象或关联数组中添加新成员,唯一的办法只有强行赋值!
5). 都可被for in遍历!
(3). 用构造函数反复创建多个相同结构的对象:
a. 问题: 以上两种创建对象的方式,一次只能创建一个对象,如果反复创建多个相同结构的对象时,重复代码会极其多!
b. 何时: 今后,只要反复创建同一类型的相同结构的多个对象时,都要用构造函数!
c. 什么是: 专门描述同一类型的所有对象的相同结构的函数
d. 为什么: 重用结构代码!
e. 如何: 2步:
1). 定义构造函数描述同一类型所有对象的同一结构
function 类型名(形参列表){
this.属性名=形参;
this.属性名=形参;
this.方法名=function(){
... this.属性名 ...
};
}
2). 调用构造函数反复创建相同结构的的多个对象
var 对象名=new 构造函数名(实参值列表)
f. 原理: new共做了几件事: 4件
1). 创建一个新的空对象:
2). ?
3). 用新对象调用构造函数
i. 先将构造函数内所有this指向新对象
ii. 通过强行赋值的方式,给新对象添加新属性和新方法
总结: 构造函数肚子里有什么将来,新对象肚子里就有什么!
4). 返回新对象的地址,给需要的变量保存起来!

5. 如何访问对象中的成员:
对象.属性名
对象.方法名()
6. this:
(1). 问题: 对象自己的方法中想使用对象自己的属性
(2). 错误: 直接在对象自己的方法中写对象自己的属性名!
报错: xxx未定义!
因为: 前边不带.的普通变量,默认只能在函数作用域和全局作用域window中查找,无权擅闯某个对象内部,获取对象中的属性值。
(3). 不好的解决: 在对象自己的方法中,用"对象名.属性名"方式来访问对象自己的属性,告诉引擎准许进入某个指定的对象内获取属性值。
缺点: 紧耦合: 外部对象名改变,方法内写死的对象名也必须跟着手动修改!如果忘记修改方法内写死的对象名,程序一定会出错!
(4). 好的解决: 用关键字this代替函数内写死的对象名:
a. 什么是this: 自动指向正在调用当前函数的.前的对象 的关键词
b. 何时: 今后只要对象自己的方法,要使用对象自己的另一个属性名或另一个方法时,都必须用"this.属性名"方式来访问!
c. 原理:
1). 当调用函数时,在临时创建的函数作用域对象中,临时创建this关键词!临时指向正在调用当前函数的.前的对象。
2). 在函数内使用this,等效于直接使用调用函数时.前的对象。
3). 如果将来调用函数时,.前的主语对象发生了变化,则this可自动跟着.前的对象一起变化,而不用修改原代码!
d. 强调: 要判断this指谁!一定不要看定义在哪儿!只看在哪里被谁调用!
三. 继承:
1. 问题: 构造函数虽然可以重用代码,但是却浪费了内存!定义在构造函数中的方法,每创建一个对象,都执行一次function,都会创建该方法的一个完全相同的副本给每个对象。——没必要的!
2. 结论: 今后在构造函数内,不要包含方法定义!
3. 解决: 继承:
4. 什么是继承: 父对象的成员,子对象无需重复创建,就可直接使用!
5. 为什么: 代码重用,节约内存!
6. 何时: 如果多个子对象,都要使用相同的功能时,就要用继承来实现
7. 如何:
(1). Js中的继承都是通过继承原型对象来实现的
(2). 什么是原型对象: 为该类型下所有子对象集中保存共有成员方法或属性的一个父级对象
(3). 如何使用:
a. 创建:
1). 不用自己创建
2). 买一赠一送的: 当我们定义构造函数时,就附赠了一个空的原型对象
b. 何时继承: 当用new创建子对象时,new的第2步是设置当前新创建的子对象继承构造函数的原型对象。
1). 每个对象上都有一个_ _proto_ _属性,用来标记当前对象的父对象是谁
2). New的第二步,将当前新对象的_ _proto_ _属性,指向当前构造函数的原型对象
c. 结果: 父对象(构造函数的原型对象)中的成员,所有子对象无需重复创建,就可直接使用!
d. 如何向原型对象中添加共有方法和属性: 强行赋值:
1). 找到当前构造函数的原型对象:
构造函数.prototype
2). 如何向原型对象中添加共有方法和属性: 强行赋值:
8. prototype vs _ _proto_ _
(1). 为所有子对象保存共有方法的父对象,成为原型对象
(2). 一个类型中,prototype 和 _ _proto_ _其实指向的是同一个原型对象
(3). 只不过:
a. prototype属于构造函数对象,是站在和原型对象平级的位置,查找构造函数: 构造函数.prototype
b. _ _proto_ _属于每个子对象中,是站在子级角度,称呼父对象。
(4). 所以,想访问一个类型中的原型对象,都用:
构造函数.prototype
想访问某一个子对象的父对象,都用子对象._ _proto_ _