各位前辈,小弟最近在看js优化相关的文章,其中有一条提到,
当函数作用域变量超出作用域范围,它就会被清理
第一次看到作用域的概念,不知道js作用域的概念是如何界定的?
那么超作用域又是如何理解的呢?
以ES5为例,大家通常说的作用域,就是指词法环境Lexical Environment。
词法环境是干嘛的:
A Lexical Environment is a specification type used to define the association of Identifiers to specific variables and functions based upon the lexical nesting structure of ECMAScript code.
就是说,词法环境是用来定义标识符与变量(和函数)的关联关系的。
简单说,作用域(即词法环境)是一个原来放置某个代码区域内的变量的容器。
那么作用域有几种?
根据规范,大概有以下几种:
global作用域
函数作用域(最常见的)
with作用域
catch作用域
new Function形成的作用域(也可以归在函数作用域中,不过性质稍有不同)
eval作用域(严格说不是,它是直接链接到外部作用域的)
作用域意味着它可以定义自己的变量。由于上述这些语法结构大都是可以循环嵌套的,所以作用域可以形成嵌套结构。而且很自然的,内部作用域可以访问外部作用域的变量,反之不行。
当JS引擎执行到某个作用域外时,通常情况下作用域内定义的变量就实现了,因为它们已经不可访问了。
但是存在一种特殊情况:假如此时作用域内的变量被它内部的函数引用了,并且此时内部函数还是可以访问的,那么作用域中的变量就不会被释放,这就形成了所谓的闭包。例如:
var a = 123;
setTimeout(function() {
alert(a);
}, 1000)
例子中,global作用域中的变量a被内部函数引用了。当所有代码执行完毕后,函数由于被setTimeout引用,无法释放,导致变量a也不能被释放。作用域以及作用域中的变量生命周期得以延长。
最后,既然题主问:作用域是怎么界定的。那么再举一个例子:
var a = 1;
function foo() {
var b = 2;
function bar() {
var c = 3;
try {
...
}
catch(e) {
...
}
}
}
console.log(a);
上例中可以形成几个作用域?
global作用域:包括函数foo外部的所有部分
函数作用域:包括foo内部,bar外部的部分
函数作用域:包括bar内部,catch外部的部分
catch作用域:包括catch内部的部分
上述都是个人观点,如有纰漏请指正。
MDN解释的还行,
首先得知道内存占用是有生命周期的:
分配你所需要的内存
使用分配到的内存(读、写)
其次尝试理解上面第三步里“释放/归还”的原理
大多数内存管理的问题都在这个阶段。在这里最艰难的任务是找到“所分配的内存确实已经不再需要了”。它往往要求开发人员来确定在程序中哪一块内存不再需要并且释放它。
高级语言解释器嵌入了“垃圾回收器”,它的主要工作是跟踪内存的分配和使用,以便当分配的内存不再使用时,自动释放它。这只能是一个近似的过程,因为要知道是否仍然需要某块内存是无法判定的 (无法通过某种算法解决).
然后了解到JavaScript
(一门高级语言)里有“垃圾回收”这个概念,下面就听听人家讲“垃圾回收”都有哪些方式,和优/缺点:
引用
引用计数垃圾收集
标记-清除算法
js中作用域是通过函数来界定了,也就是说一个函数就是一个作用域。作用域一般是在你写代码的时候就已经确定了,当然也可以在程序运行时动态的改变作用于(with语句)。作用域是很重要的概念,除此之外还有作用域链和闭包都与作用域的概念有关!