var
let
const
的区别
var
:声明函数变量。函数外用var
声明的变量会挂载在window
下,不能跨函数访问,可以跨块访问。可以重复赋值但无法删除javascript1
2
3
4
5
6
7
8function foo() {
var a = 1; // 局部变量
b = 2; // 全部变量
}
console.log(a); // 报错
console.log(c) //undefined 预编译时变量声明被提升到之前所以不报错
var c = 3;
let
:代码块({}
)内声明的变量只能在块内访问且不能跨块,跨函数访问。不能在同一个代码块中重复赋值javascript1
2
3
4
5
6
7
8
9if(1){
var a = 1;
}
console.log(a) // 1
if(1){
let a = 1;
}
console.log(a) // 报错const
:声明常量。声明时必须有赋值,不能修改值javascript1
2
3
4
5
6
7const obj = {
a : 1,
b : 2
}
obj.a = 2; // 不会报错
console.log(a) // 2
console.log(obj) // obj{a:1,b:2} obj不会发生改变
作用域
什么是作用域?
作用域的本质是运行环境:作用域对象
javascript
1 | function foo() { |
垃圾回收机制
意义:防止内存溢出(泄露)
清除的核心时间: 离开作用域的时候
如何判断函数作用域需要清楚呢?
- 标记清除:变量进入环境的时候标记为进入, 代码运行离开这个环境的时候: 标记环境离开. 垃圾回收机制启动发现这个环境已经没人了, 就开始收拾, 释放环境(内存空间释放出来)
- 引用计数:对变量引用情况统计, 如果引用次数为0, 作用域的消失直接伴随着变量文档消失,每一个变量相当于一个灯塔, 如果外界有船还需要用到这个灯塔, 灯塔会继续存在, 直到所有船都回来,这个灯塔就会消失
全局作用域在页面关闭之后才会消失
闭包
先来看下面的代码思考main
函数的作用域消失没有?
javascript
1 | function main(){ |
上面的代码实际上将private
传给了privateFromMain
,所以在main
执行完成后作用域还被保存了下来。
在上面的代码中在main
执行完成后本该被清理的作用域被保留了下来了,所以闭包就是通过函数拥有作用域链的方式保留了一段本来应该销毁的作用域链。
作用
javascript
1 | // 简单加法器的实现 |
再来看下面这个场景
javascript
1 | /* |
好处:将全局变量变成一个私有变量 => function,单独保留了访问, 限制了修改
坏处:内存溢出
循环绑定问题
javascript
1 | // 对元素点击打印序数 |
这里如果不用let
解决,那么还有什么其他解决方法来实现呢
解决问题的核心:将全局的i
转化成局部的(传参的方式),然后将函数立即执行
javascript
1 | for(var i = 0; i < liList; i++){ |
目前这个问题一律用let
声明i
来解决了
闭包思考题
javascript
1 | // Q1 |
javascript
1 | // Q2 |
闭包在开发环境中的使用
需要将商品列表中的数据按不同的字段升序降序排列该怎样做?
javascript
1 | let order = (mode,type = "asc") => { |