2.1 作用域
JavaScript代码的作用域分为两种
-
全局作用域
-
局部作用域
- 函数作用域:顾名思义就是用函数内部,这些变量都是局部变量,无论是var,let还是const,函数作用域的局部变量都会收到函数作用域的影响。
- 块作用域:定义是{}中的作用域,但是我认为它可以是for/if 中的{}或者(),在块作用域中,const和let会收到块作用域的影响。而var是不会受到块作用域的影响的,即使在var中声明了一个局部变量,也可以通过全局作用域来拿到这个变量。
有关变量作用域:在全局中用var,const,let定义的变量都是全局变量,在局部变量中定义的则是局部变量。如果在局部作用域域中,一个变量没有任何的定义就直接赋值,变量就会直接暴露在全局上下文中成为全局变量
<script>
function test(){
a12 = "2"
}
test()
console.log(a12) // "2"
</script>
2.2 作用链
作用链是一种变量查找机制,说白了就是某个在某作用域下的调用变量会先在当前作用域中寻找改变量,如果找不到这个变量,则会到它最近的上一作用域去寻找这个变量,直到找到该变量(就近原则)
2.3 js垃圾回收机制
- 标记回收机制:从根部出发,能访问到的变量将其做一个标记,将没有标记的变量回收。V8中对标记回收机制有更多的改进。
- 引用计数回收机制:对每个变量的引用的数值进行计数,当没有任何引用时,则把这个变量回收
2.4 闭包(closure)
闭包 = 内层函数 + 外层函数的变量
闭包是一个函数使用其周围环境(可以理解成父级作用域)的变量,并将这个函数返回出去,通过这个手段,我们可以通过全局作用域访问到某个局部作用域,这就是闭包。
Sample:
<script>
function c(){
a = 0
function b(){
a++
console.log(`调用了${a}次`);
}
return b
}
const temp = c()
temp()
</script>
这个例子中,b函数中的作用域访问了父作用域(c函数)中的变量a,并进行改变,在c函数中又将b函数返回出去,并赋值给了temp,temp就能访问到了 a的值。
闭包的好处:(我的理解:1:防止变量污染,2.实现了父级作用域调用子作用域)
- 封闭数据,实现数据私有,外部也可以访问函数内部的变量
- 它允许将函数与其所操作的某些数据(环境)关联起来
负面影响:内存泄漏(应该被回收掉的变量不能被回收掉了)
2.5 变量提升和函数提升
变量提升:变量提升指的是 var 声明的对象,通过var声明的对象将会被提到当前上下文的最前面去(注意的是当前被提前的只是变量的声明,如果在赋值之前访问该变量,该变量的值为undefined)
函数提升:JavaScript中函数可以先使用再声明,这依赖JavaScript的函数提升机制。在声明一个函数时,函数会被提升至当前上下文的最前面。
一个关于函数提升和变量提升的Sample:
fun()
var fun = function(){
console.log("123")//fun is not a function
}
解释:一个匿名函数,这是由于变量的提升机制,我们在声明fun的时候被提升的只有fun的定义,并没有fun的值,所以fun并没有指向这个匿名函数。
总结
以上是一些个人的理解,如有不足,欢迎指出!