要想弄清楚变量、函数等的生命周期就要先弄清楚作用域。要理解变量提升也要先弄明白作用域。今天看了作用域、作用域链、闭包方面的内容,整理出来,加深记忆。
1.作用域
-
什么是作用域?
作用域是可以访问变量、对象、函数的集合,指一个变量的作用范围。它相对于上下文对象是静态的, 在编写代码时就确定了。
作用域非常重要,它控制着变量与参数的可见性与生命周期。 -
作用域的作用是什么?
隔离变量,不同作用域下同名变量不会有冲突。
-
作用域的分类呢?
a.全局作用域
-
变量在函数外定义,就是全局变量。
-
全局作用域中的变量都是全局变量,在页面的任意的部分都可以访问到。
-
全局变量有全局作用域,直接编写在script标签中的JS代码,也都在全局作用域。
-
在全局作用域中有一个由浏览器创建的全局对象window,它代表的是浏览器的窗口,我们可以直接使用。
-
在全局作用域中创建的变量都会作为window对象的属性保存。
如下:
输出结果为:
-
在全局作用域中创建的函数都会作为window对象的方法保存。
如下:
如果变量在函数内没有声明(没有使用 var 关键字),该变量为全局变量。
如下:
b.局部(函数)作用域
-
变量在函数内声明,该变量为局部作用域,也称为函数作用域。
-
局部变量:只能在函数内使用。所以不同的函数可以使用相同的变量名称。
如下:
-
局部变量在函数开始执行时创建,执行结束后自动销毁。
函数参数:函数参数只在函数内起作用,是局部变量。
c.块级作用域(ES6新增)
- javascript中没有块级作用域的概念。ES6中新增加块级作用域。
什么是没有块级作用域?如下:
- 大括号{}中间的部分都是块级作用域。{}之中定义的所有变量在代码块外都是不可见的,所以称之为块级作用域。
- let定义的变量和const定义的常量都是块级作用域。
详细参考 块级作用域及let和const的特点及其区别
-
-
JavaScript 变量生命周期
- 变量生命周期在它被声明时初始化。
- 局部变量在函数执行完毕后销毁。
- 全局变量在页面关闭后销毁。
- 函数的参数也是局部性的,只在函数内部起作用。
2.作用域链
-
什么是作用域链:
- 作用域链(Scope Chain)是javascript内部中一种变量、函数查找机制,它决定了变量和函数的作用范围,即作用域。
- 查找变量时就是沿着作用域链来查找的。
- 当在函数作用域操作一个变量时,它会先在自身作用域中寻找,如果有就直接使用(就近原则)。如果没有则向上一级作用域中寻找,直到找到全局作用域;如果全局作用域中依然没有找到,则会报ReferenceError。
- 外部函数定义的变量可以被内部函数所使用,内部定义的则不可被外部使用。
【注意】
1.函数内部的作用域可以访问函数外部的作用域
2.如果有多个函数嵌套,那么就会构成一个链式访问结构,这就是作用域链。
如下:
变量查找规则如下:
3.闭包
-
什么是闭包?如何产生闭包?闭包的影响?注意点?
1.闭包- 私有变量会用到闭包。
- 有权访问另一个函数作用域内变量的函数都是闭包。
- 闭包就是能够读取其他函数内部数据(变量/函数)的函数。
2.闭包产生条件
- 函数嵌套,嵌套的内部(子)函数引用嵌套的外部(父)函数的变量或函数,产生闭包,内部函数不引用外部函数的变量时不会差生。
- 一个函数作为另一个函数的返回值。
- 外部函数的实参传递给另一个函数调用。
条件1示例如下:
内部plus函数访问了构造函数testcounter里面的变量i,于是就形成了闭包。下方是同样的道理。
条件2示例如下:
闭包是可访问上一层函数作用域里变量的函数,即便上一层函数已经关闭。
条件3示例如下:
3.闭包的理解。
- 闭包是嵌套的内部函数(大部分人都知道)。
- 包含被引用变量 或者函数的对象。
4.闭包的作用
- 使用函数内部的变量在函数执行完后, 仍然存活在内存中(延长了局部变量的生命周期。
- 让函数外部可以操作(读写)到函数内部的数据(变量/函数)。
- 在函数外部不能直接访问函数内部的局部变量,通过闭包让外部操作它。
5.闭包的生命周期
- 产生: 嵌套内部函数被声明时就产生了(不是在调用时)。
- 死亡: 嵌套的内部函数成为垃圾对象时死亡。(比如f = null,就可以让f成为垃圾对象。意思是,此时f不再引用闭包这个对象了)。
6.闭包的应用
- 定义具有特定功能的js模块。
- 将所有的数据和功能都封装在一个函数内部(私有的),只向外暴露一个包含n个方法的对象或函数。
- 模块的使用者, 只需要通过模块暴露的对象调用方法来实现对应的功能。
7.闭包的注意点
问题1:
由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。
解决方法:
在退出函数之前,将不使用的局部变量全部删除。
每天进步一点点,开心一点点,快乐一点点!come on!