JavaScript进阶(下)

# JavaScript 进阶 - 第3天笔记

> 了解构造函数原型对象的语法特征,掌握 JavaScript 中面向对象编程的实现方式,基于面向对象编程思想实现 DOM 操作的封装。

- 了解面向对象编程的一般特征

- 掌握基于构造函数原型对象的逻辑封装

- 掌握基于原型对象实现的继承

- 理解什么原型链及其作用

- 能够处理程序异常提升程序执行的健壮性

## 编程思想

> 学习 JavaScript 中基于原型的面向对象编程序的语法实现,理解面向对象编程的特征。

### 面向过程

面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候再一个一个的依次调用就可以了。 举个栗子:蛋炒饭!

### 面向对象

面向对象是把事务分解成为一个个对象,然后由对象之间分工与合作。

在面向对象程序开发思想中,每一个对象都是功能中心,具有明确分工。面向对象编程具有灵活、代码可复用、容易维护和开发的优点,更适合多人合作的大型软件项目。

面向对象的特性:

- 封装性

- 继承性

- 多态性

## 构造函数

对比以下通过面向对象的构造函数实现的封装:

```html```

封装是面向对象思想中比较重要的一部分,js面向对象可以通过构造函数实现的封装。同样的将变量和函数组合到了一起并能通过 this 实现数据的共享,所不同的是借助构造函数创建出来的实例对象之间是彼此不影响的

>总结:

>1. 构造函数体现了面向对象的封装特性

>2. 构造函数实例创建的对象彼此独立、互不影响封装是面向对象思想中比较重要的一部分,js面向对象可以通过构造函数实现的封装。

前面我们学过的构造函数方法很好用,但是 存在`浪费内存`的问题

## 原型对象

构造函数通过原型分配的函数是所有对象所 共享的。

- JavaScript 规定,每一个构造函数都有一个 prototype 属性,指向另一个对象,所以我们也称为原型对象

- 这个对象可以挂载函数,对象实例化不会多次创建原型上函数,节约内存

- 我们可以把那些不变的方法,直接定义在 prototype 对象上,这样所有对象的实例就可以共享这些方法。

- 构造函数和原型对象中的this 都指向 实例化的对象

``html```

了解了 JavaScript 中构造函数与原型对象的关系后,再来看原型对象具体的作用,如下代码所示:

```html```

构造函数 `Person` 中未定义任何方法,这时实例对象调用了原型对象中的方法 `sayHi`,接下来改动一下代码:

```html```

构造函数 `Person` 中定义与原型对象中相同名称的方法,这时实例对象调用则是构造函中的方法 `sayHi`。通过以上两个简单示例不难发现 JavaScript 中对象的工作机制:**当访问对象的属性或方法时,先在当前实例对象是查找,然后再去原型对象查找,并且原型对象被所有实例共享。**

```html```

总结:

**结合构造函数原型的特征,实际开发中往往会将封装的功能函数添加到原型对象中。**

### constructor 属性

在哪里? 每个原型对象里面都有个constructor 属性(constructor 构造函数)

作用:该属性指向该原型对象的构造函数, 简单理解,就是指向我的爸爸,我是有爸爸的孩子

**使用场景:**

如果有多个对象的方法,我们可以给原型对象采取对象形式赋值.但是这样就会覆盖构造函数原型对象原来的内容,这样修改后的原型对象 constructor 就不再指向当前构造函数了此时,我们可以在修改后的原型对象中,添加一个 constructor 指向原来的构造函数。

### 对象原型

对象都会有一个属性 __proto__ 指向构造函数的 prototype 原型对象,之所以我们对象可以使用构造函数 prototype 原型对象的属性和方法,就是因为对象有 __proto__ 原型的存在。

注意:- __proto__ 是JS非标准属性

- [[prototype]]和__proto__意义相同- 用来表明当前实例对象指向哪个原型对象prototype

- __proto__对象原型里面也有一个 constructor属性,指向创建该实例对象的构造函数

### 原型继承

继承是面向对象编程的另一个特征,通过继承进一步提升代码封装的程度,JavaScript 中大多是借助原型对象实现继承的特性。龙生龙、凤生凤、老鼠的儿子会打洞描述的正是继承的含义。

```html

```

① 当访问一个对象的属性(包括方法)时,首先查找这个对象自身有没有该属性。

② 如果没有就查找它的原型(也就是 __proto__指向的 prototype 原型对象)

③ 如果还没有就查找原型对象的原型(Object的原型对象)

④ 依此类推一直找到 Object 为止(null)

⑤ __proto__对象原型的意义就在于为对象成员查找机制提供一个方向,或者说一条路线

⑥ 可以使用 instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上

 

# JavaScript 进阶 - 第4天

## 深浅拷贝

### 浅拷贝

首先浅拷贝和深拷贝只针对引用类型

浅拷贝:拷贝的是地址常见方法:

1. 拷贝对象:Object.assgin() / 展开运算符 {...obj} 拷贝对象

2. 拷贝数组:Array.prototype.concat() 或者 [...arr]

>如果是简单数据类型拷贝值,引用数据类型拷贝的是地址 (简单理解: 如果是单层对象,没问题,如果有多层就有问题)

### 深拷贝

首先浅拷贝和深拷贝只针对引用类型

深拷贝:拷贝的是对象,不是地址

常见方法:

1. 通过递归实现深拷贝

2. lodash/cloneDeep

3. 通过JSON.stringify()实现

### 递归实现深拷贝

函数递归:如果一个函数在内部可以调用其本身,那么这个函数就是递归函数

- 简单理解:函数内部自己调用自己, 这个函数就是递归函数

- 递归函数的作用和循环效果类似

- 由于递归很容易发生“栈溢出”错误(stack overflow),所以必须要加退出条件 return

~~~html

~~~

#### js库lodash里面cloneDeep内部实现了深拷贝

~~~html

~~~

#### JSON序列化

~~~html

~~~

## 异常处理

> 了解 JavaScript 中程序异常处理的方法,提升代码运行的健壮性。

### throw

异常处理是指预估代码执行过程中可能发生的错误,然后最大程度的避免错误的发生导致整个程序无法继续运行

总结:

1. throw 抛出异常信息,程序也会终止执行

2. throw 后面跟的是错误提示信息

3. Error 对象配合 throw 使用,能够设置更详细的错误信息

```html```

### try ... catch

```html```

总结:

1. `try...catch` 用于捕获错误信息

2. 将预估可能发生错误的代码写在 `try` 代码段中

3. 如果 `try` 代码段中出现错误后,会执行 `catch` 代码段,并截获到错误信息

### debugger相当于断点调试

## 处理this

> 了解函数中 this 在不同场景下的默认值,知道动态指定函数 this 值的方法。

`this` 是 JavaScript 最具“魅惑”的知识点,不同的应用场合 `this` 的取值可能会有意想不到的结果,在此我们对以往学习过的关于【 `this` 默认的取值】情况进行归纳和总结。

### 普通函数

**普通函数**的调用方式决定了 `this` 的值,即【谁调用 `this` 的值指向谁】,如下代码所示:

```html```

注: 普通函数没有明确调用者时 `this` 值为 `window`,严格模式下没有调用者时 `this` 的值为 `undefined`。

### 箭头函数

**箭头函数**中的 `this` 与普通函数完全不同,也不受调用方式的影响,事实上箭头函数中并不存在 `this` !箭头函数中访问的 `this` 不过是箭头函数所在作用域的 `this` 变量。

```html```

在开发中【使用箭头函数前需要考虑函数中 `this` 的值】,**事件回调函数**使用箭头函数时,`this` 为全局的 `window`,因此DOM事件回调函数不推荐使用箭头函数,如下代码所示:

```html```

同样由于箭头函数 `this` 的原因,**基于原型的面向对象也不推荐采用箭头函数**,如下代码所示:

```html```

### 改变this指向

以上归纳了普通函数和箭头函数中关于 `this` 默认值的情形,不仅如此 JavaScript 中还允许指定函数中 `this` 的指向,有 3 个方法可以动态指定普通函数中 `this` 的指向:

#### call

使用 `call` 方法调用函数,同时指定函数中 `this` 的值,使用方法如下代码所示:

```html```

总结:

1. `call` 方法能够在调用函数的同时指定 `this` 的值

2. 使用 `call` 方法调用函数时,第1个参数为 `this` 指定的值

3. `call` 方法的其余参数会依次自动传入函数做为函数的参数

#### apply

使用 `call` 方法**调用函数**,同时指定函数中 `this` 的值,使用方法如下代码所示:

```html```

总结:

1. `apply` 方法能够在调用函数的同时指定 `this` 的值

2. 使用 `apply` 方法调用函数时,第1个参数为 `this` 指定的值

3. `apply` 方法第2个参数为数组,数组的单元值依次自动传入函数做为函数的参数

#### bind

`bind` 方法并**不会调用函数**,而是创建一个指定了 `this` 值的新函数,使用方法如下代码所示:

```html```

注:`bind` 方法创建新的函数,与原函数的唯一的变化是改变了 `this` 的值。

## 防抖节流

1. 防抖(debounce)所谓防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间

2. 节流(throttle)所谓节流,就是指连续触发事件但是在 n 秒中只执行一次函数

 

你可能感兴趣的:(前端JaveScript学习,javascript,前端)