目录
1.作用域
1.1作用域的概念
1.2作用域的分类
1.2.1全局作用域
1.2.2局部作用域
1.2.3块级作用域(ES6新增 )
2.变量作用域
2.1全局变量
2.2局部变量
3.作用域链
3.1作用域链的定义
4.垃圾回收机制
4.1定义
4.2如何避免内存泄漏
5.预解析
1.作用域
1.1作用域的概念
我们平时声明的变量的名字,并不是在所有地方都有效,限定这个名字的可用范围,就是这个名字所在的作用域。作用域的使用可以提高程序逻辑的局部性,增强了程序的可靠性,同时可以减少命名冲突的问题。
1.2作用域的分类
作用域分为全局作用域、局部作用域和块级作用域(es6新增)三种。
1.2.1全局作用域
在全局范围(script标签内部,或者独立的js文件)内都生效(函数内和外都可以访问到)。
1.2.2局部作用域
也叫函数作用域,只有函数内才能访问到
1.2.3块级作用域(ES6新增 )
- { }表示一个块级作用域,一个循环或者一个条件语句都是一个块级作用域。
- ES6才有块级作用域,之前都是没有的。
-
在其他编程语言中(如java、c#等),或在es6中,let声明的变量只在它所在的代码块有效,所以在外部是访问不到的。
2.变量作用域
2.1全局变量
- 在全局作用域下声明的变量叫全局变量(在函数外部定义的变量)
- 函数内外都能使用
- 声明周期比较长,只有页面关闭才销毁
- 如果函数内,没有声明变量,直接使用,也会将这个变量升级为全局变量 eg: a=10;
2.2局部变量
- 在函数内声明的变量是局部变量。
- 局部变量只能在函数内使用。
- 生命周期短,函数一旦被调用,变量就销毁,及时释放内存。
- 函数形参部分,也是局部变量。
- 如果在函数内部用var声明一个变量,那么这个变量也是局部变量。
- 局部变量只在函数内部进行使用。
3.作用域链
3.1作用域链的定义
作用域链就是变量可用范围的一种查找机制,函数套函数,每个函数都有自己的作用域,首先先从当前作用域中查找,如果查不到,则向上层作用域查找,直到找到全局,找到了就可以使用,找不到就报错,这种链式查找关系,就叫作用域链(其实就是一层一层向上查找作用域,看看能不能找到所用变量的定义信息,要是都找不到,那就得报错)。
比较官方的解释:根据在内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问,就称为作用域链。
function f1() {var num = 123;function f2() {var num = 0;console.log(num); // 站在目标出发,一层一层的往外查找}f2();}var num = 456;f1();
4.垃圾回收机制
4.1定义
当已经不需要某块内存时,但这块内存还未能释放出来这就叫内存泄漏,而垃圾回收机制就是为了防止内存泄漏,所以不定时的寻找到不再使用的变量,并将这些内存释放出来。
4.2如何避免内存泄漏
- 尽量减少使用全局变量,多使用局部变量。
- 在代码中多使用函数封装。
- 移除被遗忘的定时器或回调函数
- 及时释放闭包中的变量。
- DOM的引用时 不再使用的DOM要及时清除。
- 数组和对象在使用完时要置空。
5.预解析
JavaScript代码是由浏览器中的JavaScript解析器来执行的。JavaScript解析器在运行JavaScript代码的 时候分为两步:预解析和代码执行。
- 预解析: "var 和 function”声明的两个变量在内存中 进行提前声明或者定义(其实就是变量或函数提升)。
- 代码执行:从上到下执行JS语句。
// 源程序var a = 18;f1();function f1() {var b = 9;console.log(a);console.log(b);var a = '123';}// ----------------// 按照预处理解析过的程序var a;//函数和var声明都要提前function f1() {// 函数内部的声明也要提前var a;var b;b = 9;console.log(a); //undefinedconsole.log(b); //9 a = '123';}a = 18;f1();
// 源程序f1();console.log(c);console.log(b);console.log(a);function f1() {var a = b = c = 9;//var a;// a = b = c = 9;// 相当于 var a = 9; b = 9; c = 9; b 和 c 直接赋值 没有var 声明 当 全局变量看// 集体声明 var a = 9, b = 9, c = 9;console.log(a);console.log(b);console.log(c);}// ----------------// 按照预处理解析过的程序function f1() {var a;a= b = c = 9;console.log(a);//9console.log(b);//9console.log(c);//9}f1();console.log(c);//9console.log(b);//9console.log(a);//报错