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;
- es5中循环和条件语句后面跟的花括号里面定义的变量都是全局变量
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.垃圾回收机制
.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); //undefined console.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);//9 console.log(b);//9 console.log(c);//9 } f1(); console.log(c);//9 console.log(b);//9 console.log(a);//报错