(一)
##### 一、面向对象
1.`OOP`:面向对象编程,一种编程思想 -- 低耦合,高内聚,抽象
2.面向过程编程:按照步骤一步一步写代码 -- 好理解,耦合性高,代码冗余
3.面向对象三大特性:封装、继承、多态
、封装
1.将代码按照面向对象的思想写出来 -- 如何创建对象《- 构造函数
2.如何创建一个对象:
```js
直接创建一个对象:
1.使用Object构造函数:var obj = new Object;
2.使用字面量:var obj = {}
3.使用Object.create()方法:var obj = Object.create()
Object.create(obj):以obj作为原型创建一个新对象
使用函数创建对象:
4.使用工厂模式创建对象
5.使用构造函数创建对象
```
3.构造函数:普通函数使用`new`调用 -- `JS`中没有类,使用构造函数模拟
```
一个函数到底是构造函数还是普通函数取决于它的调用方式
```
4.构造函数和普通函数区别:1.调用方式不同:普通函数调用必须使用函数名加上`()`;构造函数必须使用`new`关键字调用,可以加上`()`,也可以不加(没有参数加不加都可以;有参数传递则需要加上`()`)
2.返回值不同:普通调用之后返回`return`的值;构造函数返回一个对象
3.`this`指向不同:普通函数指向调用者;构造函数指向实例本身
4.命名规则不同:普通函数使用小驼峰命名;构造函数使用大驼峰命名
5.构造函数组成:由属性及方法组成
6.按访问程度分类:私有属性/方法;公有属性/方法;静态属性/方法
7.私有属性/方法:直接声明的属性(变量)或方法(函数) -- 只能在构造函数内使用,实例不能继承
```js
function Person(){
var money = 1000; //私有属性
}
```
8.静态属性/方法:直接写在构造函数上的属性或方法 -- 属于构造函数;子类不能调用;使用构造函数直接调用
9.公有属性/方法:实例属性/方法;原型属性/方法
10.实例属性/方法:绑定在`this`对象上 -- 实例之间不共享
11.原型属性/方法:绑定在`prototype`对象上 -- 实例之间共享
12.`prototype`对象:原型对象,存在于实例中,不能直接通过`prototype`访问,要通过`__proto__`访问,主要包含以下内容
```
1.原型属性/方法
2.构造函数:constructor
3.父的prototype属性
```
13.`instanceof`:判断一个构造函数的`prototype`属性是否出现在实例的原型链上
14.原型链:每个实例都拥有一个`__proto__`属性,指向父的`prototype`,这个属性可包含三部分内容:原型属性/方法;构造函数(`constructor`);`__proto__`,这个`__proto__`指向父的父的`prototype`属性,依次向上,到`__proto__`指向`null`为止 -- 最终会指向`Object`,`Object.__proto__=null`
![原型链](D:\Teaching\H2201\day58-面向对象封装\原型链.png)
15.`bind(obj)`:将函数的`this`指向为`obj`
(二)
一、继承(Extends)
1.生活中:子承父业;继承遗产;继承父母的DNA
.... -- 父子关系;哪些可以被继承
2.程序中:子类继承父类的属性及方法 -- 实例及原型的属性/方法
二、实现方式
1.在子类中获取父类的实例,遍历实例属性/方法并将绑定到子类的实例(this
)或原型上
优点:可以继承父类所有的属性/方法 缺点:继承链不完整 -- 没有父类
2.在子类中使用this
/原型调用父类的构造函数:bind()
,call()
,apply()
优点:简单 缺点:只能继承实例属性/方法;继承链不完整
3.将父类的原型对象绑定到子类原型对象上
优点:继承父类的原型属性/方法 缺点:父类和子类共用了原型对象 -- 继承链混乱 不能继承实例属性/方法
4.将父类的原型对象绑定到一个空对象然后赋值给子的原型
优点:保证原型链完整;子类和父类不再共用一个原型 缺点:只能继承父类的原型属性/方法
5.将父类的实例绑定到子类的原型
function Child(arg1,arg2){ this.__proto__ = new Parent(arg1,arg2); this.__proto__.construtor = Child; //父的实例中构造函数指向为父类,需要手动改为子类 }
6.普通对象继承:
三、其他
改变函数内的this指向/使用指定对象调用函数
1.bind()
:改变函数内的this
指向并返回这个函数 -- 如果要调用这个函数就需要在后面加上括号
2.call(obj,arg1,arg2...)
:改变函数内的this
指向并执行这个函数
3.apply(obj,[arg1,arg2...])
:改变函数内的this
指向并执行这个函数
基本数据类型&引用数据类型
1.基本数据类型:数值;字符串;布尔值...
变量名和值都存储在栈中
2.引用数据类型:数组、对象、函数
变量名存储在栈中,值存储在堆中,变量名保存的实际是值在堆中的地址
3.区别:赋值时,基本数据类型是将值赋值给另一个变量;引用数据类型是将地址赋值给另一个变量(多个变量会指向同一个地址--一个变量变化,另一个也会跟着变化)
4.浅拷贝:引用数据类型直接赋值 -- 一个变量发生变化另一个跟着变化
5.深拷贝:引用数据类型拷贝的是值 -- 一个变量发生变化另一个不受影响
1.通过已有函数实现简单深拷贝:只复制第一层;有些特殊值不能复制 2.递归遍历所有的值
new操作符做了什么?
1.创建了一个空对象
2.给对象绑定原型对象
3.将this
和对象绑定
4.返回对象
(三)
一、多态
1.对有继承关系的类延伸的概念 -- 重写、重载
2.通过参数的个数、数据类型、返回值等实现同一个方法有不同的方法体
3.JS
是弱类型语言,变量的数据类型会随着所赋的值改变 -- JS
中没有多态
二、this指向
1.普通全局函数,this
指向window
,严格模式下("use strict"
)指向undefined
2.事件监听器中,this
指向事件源
3.计时器中,this
指向window
4.普通对象中,this
指向对象本身
5.构造函数中,this
指向实例
6.call()/applay()/bind()
调用的函数,函数内的this
指向第一个参数,如果没有参数,指向window
,严格模式下指向undefined
7.大原则:谁调用指向谁