- 首先了解环境的概念:决定变量或函数有权访问的其他数据。
- 作用域决定了变量和函数的可见性和生命周期。
- 块级作用域: 在javascript中,函数里面定义的变量,可以在函数里面被访问,但在函数外无法访问。而由花括号封闭的代码块都有自己的作用域,因而支持根据条件来定义变量,变量在执行完毕后会被销毁。
ES5中没有块级作用域
影响
- if内层变量可能覆盖外层变量:
var tmp = new Date();
function f(){
console.log(tmp);
if(false){
var tmp = "hello";
}
}
f(); // undefined
- 以上代码执行后,输出函数f的结果为undefined,因为if会将增加的变量添加到当前执行环境中(即全局环境中)覆盖外层的变量---”变量提升“
- for循环的变量会泄露成全局变量
var s = "hello";
for(var i=0;i<s.length;i++){
console.log(s[i]);
}
console.log(i); // 5
- for循环中的i本来在执行后被销毁,但是没有消失反而成了全局变量
ES6中引入let和const命名后有了块级作用域
- ES6 新增了
let
命令,用来声明变量。它的用法类似于var
,但是所声明的变量,只在let
命令所在的代码块内有效。
更多详情
总结
- var命令下没有块级作用域
- 使用var会形成一个未初始化的undefined的值
- if函数会出现“变量提升”的现象
- for循环定义的变量会泄露成全局变量
- ES6中的let和const命令有块级作用域
- let和const适合在for循环使用,只在循环体内有效,体外会报错
for循环的特别:
设置循环变量的部分是父作用域,循环体内是子作用域
- 不存在“变量提升”
- 会出现暂时性死区(TDZ):只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。规范编程人员先进行变量的声明后才可进行使用。
- 不允许重复声明,但内层作用域可以定义外层作用域的同名变量
- 允许块级作用域任意嵌套
- 不再需要立即执行函数表达式(IIFE)
针对ES6 的浏览器有效:
- 允许在块级作用域内声明函数。
- 函数声明类似于var,即会提升到全局作用域或函数作用域的头部。
- 同时,函数声明还会提升到所在的块级作用域的头部。