**
作用域链
**
- 由于作用域是相对于变量而言的,而如果存在多级作用域,这个变量又来自于哪里?这个问题就需要好好地探究一下了,我们把这个变量的查找过程称之为变量的作用域链
- 作用域链的意义:查找变量(确定变量来自于哪里,变量是否可以访问)
- 简单来说,作用域链可以用以下几句话来概括:(或者说:确定一个变量来自于哪个作用域)
-----查看当前作用域,如果当前作用域声明了这个变量,就确定结果
------查找当前作用域的上级作用域,也就是当前函数的上级函数,看看上级函数中有没有声明
------再查找上级函数的上级函数,直到全局作用域为止
------如果全局作用域中也没有,我们就认为这个变量未声明(xxx is not defined)
js的作用域分两种,全局和局部,基于我们所熟悉的作用域链相关知识,我们知道在js作用域环境中访问变量的权利是由内向外的,内部作用域可以获得当前作用域下的变量并且可以获得当前包含当前作用域的外层作用域下的变量,反之则不能,也就是说在外层作用域下无法获取内层作用域下的变量,同样在不同的函数作用域中也是不能相互访问彼此变量的,那么我们想在一个函数内部也有限权访问另一个函数内部的变量该怎么办呢?闭包就是用来解决这一需求的,闭包的本质就是在一个函数内部创建另一个函数。
我们首先知道闭包有3个特性:
①函数嵌套函数
②函数内部可以引用函数外部的参数和变量
③参数和变量不会被垃圾回收机制回收
<script>
function fn(){
var age = 30;
return function fn2(){
return age;
}
}
var a1= fn();
console.log(a1());
</script>
在这段代码中,a()中的返回值是一个匿名函数,这个函数在a()作用域内部,所以它可以获取a()作用域下变量name的值,将这个值作为返回值赋给全局作用域下的变量b,实现了在全局变量下获取到局部变量中的变量的值
for(let i=0;i<5;i++){
setTimeout(function(){
console.log(i);
},1000);
}
for(let i=0;i<5;i++){
setTimeout(function(){
console.log(i);
},1000);
}
for(var i=0;i<list.length;i++){
console.log(i);
list[i].onclick=function(){
console.log(i);
}
}
由于es6里面是有块级作用域的。 在每次遍历之前就会生成一个块级的作用域,而每个作用域互不干扰 也就是会生成lists.length个这种作用域来分别保存变量i的值,作为局部变量 既然是局部变量,那么 点击第一个li,在执行的时候根据作用域链的规则 访问的肯定是当前作用域里的 i 即:点击第一个li访问到了 第一个作用域(局部) 里的变量 这样看的话,是符合闭包的概念的,当然也是闭包
为什么let可以解决闭包? var声明的变量,在全局范围内都有效,所以全局只有一个变量i。每一次循环,变量i的值都会发生改变。 let声明的变量,仅在块级作用域内有效,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量。而JavaScript
引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。
问题: 内存泄露;