一,let和const命令
let命令用来声明变量,他的作用类似于var,但是所声明的变量只在let命令所在的代码块内部有效,不像var那样,会发生变量提升现象;
for()循环的计数器,适合使用let命令;
for(let i =0;i<5;i++){
}
console.log(i);//ReferenceError :i is not defined
暂时性的死区
var name="MGT360124";
if(true){
name = "YSS360124";//ReferenceError
let name;
}
全局变量name,但是块级作用域内有let又声明了一个局部变量name;
导致后者绑定这个块级作用域,所以在let声明变量前,对name赋值会报错;所以在代码块内,使用let命令声明变量之前,该变量都是不可用的,在语法上称为"暂时性死区"(TDZ);
‘’暂时性的死区‘’也意味着typeof不再是一个百分之百安全的操作;
{
typeof name;//ReferenceError
let name;
}
ES5 只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理的场景。
第一种场景,内层变量可能会覆盖外层变量。
var name = "MGT360124";
function getName(){
console.log(name);
var name="YSS360124"
}
getName();//undefined
第二种场景,用来计数的循环变量泄露为全局变量。
for(var i=0;i<5;i++){
}
console.log(i);//5
ES6的块级作用域
{
let name = "MGT360124";
}
name;
ES6 允许块级作用域的任意嵌套。
{{{{
{let insane = 'Hello World'}
console.log(insane); // 报错
}}}};
do表达式
块级作用域是一个语句,将多个操作封装在一起,没有返回值。
使用do表达式,使得块级作用域可以变为表达式,也就是说可以返回值;
let x = do{
let t = f();
t * t + 1;
}//变量x会得到整个块级作用域的返回值
const 命令
const声明一个只读的常量。一旦声明,常量的值就不能改变。
const PI = 3.1415;
PI // 3.1415
PI = 3;
// TypeError: Assignment to constant variable.
const声明的变量不得改变值,这意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值。const foo; // SyntaxError: Missing initializer in const declaration
const的作用域与let命令相同:只在声明所在的块级作用域内有效。const命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用。
const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址不得改动,对于简单数据类型(数值,字符串,布尔值),值就保存在变量指向的那个内存地址,因此等同于常量,但是对于复合类型的数据(对象和数组)变量指向的内存地址,保存的只是一个指针,const只能保证这个指针第固定的,至于他指向的数据结构是不是可变的,就完全不能控制了;
const foo = {};
foo.prop=123;//为foo添加一个属性
foo.prop;//123
foo={}//将foo指向另一个对象,就会报错
常量foo储存的是一个地址,这个地址指向一个对象,不可变的只是这个地址,
即不能把foo指向另一个地址,但是对象本身是可变的,所以依然可以为其添加新属性;
const a = [];
a.push("hello");
a.length = 0;
a=["world"];//报错
顶层对象的属性
顶层对象,在浏览器环境指的是window对象,在node指的是global对象;
顶层对象的属性和全局变量挂钩,被认为是js中最大的失败;ES6为了改变这一点,并保持兼容性,var 命令和function命令声明的全局变量,依旧是顶层对象,另一方面规定:let命令和const命令,class命令声明的全局变量不再属于顶层对象的属性,也就是说:从ES6开始,全局变量将逐渐与鼎城对象的属性脱钩;
var name="MGT360124";
window.name;//MGT360124
let age=18;
window.age;//undefined
ES5的顶层对象,本身也是个问题,因为他在各种实现里面是不统一的;
1,浏览器里面,顶层对象是window,但是node和web workers(Web Workers 是 HTML5 提供的一个javascript多线程解决方案)没有window
2,浏览器和web Workers里面,self也是指向顶层对象,但是node没有self
3,node里面顶层对象时global,但是其他环境都不支持;
同一段代码为了能够在各种环境,都能取得到顶层对象,一般用this变量,但是也有局限性。
1, 全局环境中,this会返回顶层对象。但是node模块和ES6模块中this
返回的是当前模块;
2,函数里面的this,如果函数不是作为对象的方法运行,而是单纯作为函数运行,那么this会指向顶层对象,但是在严格模式下,this会返回undefined;