作用域和作用域链
1.作用域
理解:
- 就是一块地盘,一个代码所在的区域
- 它是静态的(相对于上下文对象),在编写代码的时候就已经确定
分类:
- 全局作用域
- 局部作用域
- 块作用域(ES6)
作用:
- 隔离变量,不同作用域下同名变量不会有冲突
2.作用域和执行上下文
1).区别1
- 全局作用域之外,每个函数都会创建自己的作用域,作用域在函数定义时就已经确定,而不是在函数调用时
- 全局执行上下文环境是在全局作用域确定之后,js代码马上执行之前创建
- 函数执行上下文是在调用函数时,函数体代码执行之前创建
2).区别2
- 作用域是静态的,只要函数定义好了就会一直存在,且不会再变化
- 执行上下文环境是动态的,调用函数时创建,函数调用结束时上下文环境会被动态释放
3).联系
- 执行上下文环境(对象)是从属于所在的作用域
- 全局上下文环境---->全局作用域
- 函数上下文环境---->对应的函数使用域
3.作用域链
1).理解
- 多个上下级关系的作用域形成的链,它的方向是从下向上的(从内到外)
- 查找变量时就是沿着作用域链来查找的
2).查找一个变量的规则
- 在当前作用域下的执行上下文中查找对应的属性,如果有直接返回,否则进入2
- 在上一级作用域的执行上下文查找对应的属性,如果有直接返回,否则进入3
- 再次执行2的相同操作,直到全局作用域,如果还找不到就抛出找不到的异常
图解:
面试题:
1).
<script type="text/javascript">
var x = 10;
function fn() {
console.log(x) // 10
}
function show(f) {
var x = 20
f()
}
show(fn)
</script>
2).
<script type="text/javascript">
var fn = function () {
console.log(fn) //输出fn函数
}
fn()
var obj = {
fn2: function () {
console.log(fn2) //报错 fn2未定义
}
}
obj.fn2()
</script>
闭包
1.闭包的理解
1).如何产生闭包?
- 当一个嵌套的内部(子)函数引用了嵌套的外部(父)函数的变量(函数)时,就产生了闭包
2).闭包到底是什么?
- 理解一:闭包是嵌套的内部函数
- 理解二:包含被引用变量(函数)的对象
- 注意:闭包存在于嵌套的内部函数中
3).产生闭包的条件?
- 函数嵌套
- 内部函数引用了外部函数的数据(变量/函数)
2.常见的闭包
- 将函数作为另一个函数的返回值
function fn1() {
var a = 2
function fn2() {
a++
console.log(a)
}
return fn2
}
var f = fn1()
f() // 3
f() // 4
- 将函数作为实参传递给另一个函数调用
function showDelay(msg, time) {
setTimeout(function () {
alert(msg)
}, time)
}
showDelay('hello', 1000)
3.闭包的作用
- 延长了局部变量的生命周期
- 在外部能够间接的操作内部的变量
4.闭包的生命周期
- 产生:在嵌套内部函数定义执行完时就产生了(不是在调用)
- 死亡:在嵌套的内部函数成为垃圾对象时
<script type="text/javascript">
function fn1() {
var a = 2
function fn2() {
a++
console.log(a)
}
return fn2
}
// 问题1:此时闭包产生了吗? 已产生
var f = fn1()
// 问题2:此时闭包释放了吗? 没有
f()
f()
// 问题3:此时闭包释放回收了吗? 没有
// 问题4:如何让闭包释放回收呢? f = null
</script>
5.闭包的应用
自定义JS模块
- 具有特定功能的js文件
- 将所有的数据和功能都封装在一个函数内部(私有的)
- 只向外部暴露一个包含n个方法的对象或函数
- 模块的使用者,只需要通过模块暴露的对象调用方法来实现对应的功能
6.闭包的缺点以及解决
缺点
- 函数执行完后,函数内的局部变量没有释放,占用内存时间会变长
- 容易造成内存泄露
解决
- 能不用闭包就不用
- 及时释放
内存溢出与内存泄露
1.内存溢出
- 一种程序运行出现的错误
- 当程序运行需要的内存超过了剩余的内存时,就会抛出内存溢出的错误
2.内存泄露
- 占用的内存没有及时释放
- 内存泄露积累多了就容易导致内存溢出
- 常见的内存泄露:
- 意外的全局变量
- 没有及时清理的计时器或回调函数
- 闭包