# 原型链
- 概念:JS里面的对象可能会有父对象,父对象还会有父对象
- 根本:原型链的根本是继承
对象中几乎都有一个__proto__
属性,指向他的父对象,可以实现让该对象访问到父对象种的相关属性 - 根对象:
Object.prototype
let arr = [1, 3, 5] // arr.__proto__: Array.prototype // arr.__proto__.__proto__: 根对象 function Animal () {} let cat = new Animal() // cat.__proto__: Animal.prototype // cat.__proto__.__proto__: 根对象
1
2
3
4
5
6
7
# 闭包
# 变量作用域
- 概念:一个变量可以使用的范围叫做变量作用域
- 全局作用域:最外层的作用域
- 独立作用域:JS中还可以通过函数创建出一个独立的作用域,其中函数可以嵌套,所以作用域也可以嵌套
let age = 18 // 全局变量
function f1 () {
let name = 'haha' // f1函数内部的变量
}
1
2
3
4
2
3
4
变量的声名和赋值是在两个不同时期的
fn函数执行的时候,首先找到函数内部所有的变量、函数声名,把他们放在作用域中,给变量一个初始值undefined
然后逐条执行代码,在执行代码的过程中,如果有赋值语句,对变量进行赋值
# 作用域链
- 概念:由于作用域是相对于变量而言的,而如果存在多级作用域,那变量的查找过程就叫做变量的作用域链
- 意义:查找变量
- 确定变量来自于那个作用域
- 变量是否可以访问
- 难点:看上一级作用域,不是看函数在哪里调用,而是看函数在哪里编写,因为这种特别,我们通常会把作用域说成是词法作用域
查看当前作用域,如果当前作用域声名了这个变量,就确定结果,然后查找当前作用域的上级作用域,也就是当前函数的上级函数,看看上级函数中有没有声名,直到全局作用域为止,如果全局作用域中也没有,我们就认为这个变量没声明
# 闭包的产生
function fn() {
var a = 5
return function () {
a++
}
}
var f1 = fn()
f1()
f1()
f1()
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
- 一般认为函数执行完毕,变量就会释放
- 但是由于js引擎发现匿名函数要使用a变量,所以a变量并不能得到释放,而是把a变量放在匿名函数可以访问到的地方去了。
- a变量存在于f1函数可以访问到的地方,此时a变量只能被f1函数访问
- 再次执行fn会初始化一个新的a变量
- 可以通过
f1 = null
来释放f1里面保存的a变量
# 闭包的应用场景
- 模块化
- 防止变量被破坏