let命令
- let命令只在所在的代码块内有效
- let命令很适合for循环的计数器
- let命令不存在变量提升,在变量声明前使用会报ReferenceError错误
- let不允许在相同的作用域内,重复声明同一个变量
块级作用域
ES5只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理场景。
第一种场景:内层变量可能会覆盖外层变量。
var tmp = new Date();
function f() {
console.log(tmp);
if (false) {
var tmp = 'hello world';
}
}
f(); // undefined
//解释
/*函数内部if代码块外部使用外层的tmp变量,内部使用内层的tmp变量,但是由于存在
*变量提升,内层的tmp覆盖了外层的tmp变量
*/
第二种场景:用来计数的循环变量泄露为全局变量
var s = 'hello';
for (var i = 0; i < s.length; i++) {
console.log(s[i]);
}
console.log(i); // 5
/*
*循环变量i只用来控制循环,但是循环结束后,他并没有小时,泄露成了全局变量
*/
ES6的块级作用域
let和const为JavaScript提供了块级作用域
ES6允许块级作用域的多级嵌套
{{{
let test = 12;
{let text = 12;}
}}}
块级作用域的出现,使用立即执行函数来防止污染全局变量已经不再必要了
块级作用域域函数声明
ES5规定,函数只能在顶层作用域和函数作用域之中声明,不能在块级作用中声明函数,但是浏览器没有遵守这个规定,为了兼容以前的旧代码,还是支持在块级作用域之中声明函数
例子:
function f() { console.log('I am outside!'); }
(function () {
if (false) {
// 重复声明一次函数f
function f() { console.log('I am inside!'); }
}
f();
}());
在ES5环境中运行,if内声明的函数会被提升到函数头部:
// ES5 环境
function f() { console.log('I am outside!'); }
(function () {
function f() { console.log('I am inside!'); }
if (false) {
}
f();
}());
ES6引入块级作用域后,明确允许在块级作用域之中声明函数.函树声明语句的行为类似于let,在块级作用域之外不可引用.
但是ES6规定,浏览器的实现可以不遵守上面的规定,有自己的行为方式(为了兼容以前的老代码).
- 允许在块级作用域内声明函数
- 函数声明类似于var,即会提升到全局作用域或函数作用域的头部。
- 同时,函数声明还会提升到所在的块级作用域的头部。
注意:上面的三条规则只对ES6的浏览器实现有效,其他浏览器环境的实现不用遵守
上面的例子在ES6环境中运行如下:
// 浏览器的 ES6 环境
function f() { console.log('I am outside!'); }
(function () {
var f = undefined;
if (false) {
function f() { console.log('I am inside!'); }
}
f();
}());
// Uncaught TypeError: f is not a function
综上所述,应该避免在块级作用域内声明函数,如果确实需要,也应该写成函数表达式,而不是函数声明语句。
注意:ES6块级作用域必须有大括号,如果没有大括号,JavaScript引擎就认为不存在块级作用域
const命令
const声明一个只读的常量,一旦声明,常量的值就不能改变。
const一旦声明了变量,就必须立即初始化,不能留到以后赋值,不然会报错。
const声明的变量也是不存在变量提升的,不能重复声明。
本质
const定义的常量不是变量的值不得改动,而是变量指向的的那个内存地址保存的数据不得改动
- 对于简单类型的数据(数值,字符串,布尔值),值就保存在变量指向的那个内存地址,因此等同于常量
- 对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的,但是它指向的数据结构是不是可变的就不能控制了
顶层对象的属性
在ES5中,全局变量就等同于顶层对象(window)的属性,这非常不利于模块化编程,因为顶层对象的属性到处都可以修改。
ES6中的let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性。
this指向
- 全局环境中,this会返回顶层对象。但是,Node模块和ES6模块中,this返回的是当前模块
- 函数里面的this,如果函数不是作为对象的方法运行,而是单纯作为函数运行,this会指向顶层对象,否则会指向当前对象(运行环境)
暂时性死区
概念:使用let或const命令声明变量之前,该变量都是不可用的,这在语法上,称为"暂时性死区".
暂时性死区意味着typeof不再是一个百分之百安全的操作.
例子:
typeof x; //ReferenceError
let x;
来源:CSDN
作者:Ewar
链接:https://blog.csdn.net/qq_25405005/article/details/103605782