let与cont命令
let命令
声明
let可以用来声明一个变量,与var相似。
但是var声明的变量是全局的,而let声明的变量只有在声明let的块中有效
{
let a=10;
var b=1;
}
a//会报错a是defined
b//1
不存在变量提升
var声明一个变量,如果在声明前就调用的话不会报错,这就是变量提升
但是let的话就不行,如果let在声明前就调用的话会报错,因为它不存在变量提升
console.log(a);//不会报错,但也不会输出下面的赋值,而是输出undefinde
var a=2;
console.log(b);//会报错ReferenceError(应用错误)
let b=2;
这也就是说在运行开始的时候a就已经存在了,但是并没有进行赋值,而b是不存在的。
暂时性死区
如果区块中存在let命令,那么在let命令声明变量之前,该变量都是不可用的,这就是暂时性死区
if(true){
//暂时性死区开始
tmp='abc';//报错
console.log(tmp)//报错
let tmp//暂时性死区结束(因为这里用let声明了tmp变量)
console.log(tmp);//undefined(没有赋值)
tmp=123;//赋值
console.log(tmp);//输出123
}
而且就算你在块外用var给一个变量赋值了,在块内再用let声明一遍的话,内部完全与外部隔离,不受外部的影响(如下:)
var tmp = 123;//用var声明变量tmp并赋值
if (true) {
tmp = 'abc'; // 报错引用错误,也就是说完全没有访问到var声明的tmp
let tmp=234;//声明tmp并赋值
console.log(tmp);//输出234
}
不允许重复声明
let不允许在相同作用域内重复声明同一个变量,因此不能在函数内部重新声明参数。
那么,反过来说,在不同作用域内可以重复声明同一个变量。
let tmp = 123;//在外面声明tmp并赋值123
if(tmp==123){
let tmp='ABC';//在里面声明tmp并赋值ABC
console.log(tmp);//打印出ABC
}
console.log(tmp);//打印出123
块级作用域
1.在层内外有两个相同名称的变量,如果内对内层变量进行赋值的话,有可能会赋值外层变量(如下:)
var tmp = new Date();//新建一个函数对象
function f() {
console.log(tmp);//undefined(原因在于变量提升,内层的tmp变量覆盖了外层的)
if (false) {
var tmp = 'hello world';//声明tmp变量
}
}
console.log(f()); // undefined
2.for循环里的循环变量泄露为全局全局变量
var s = 'hello';
for (var i = 0; i < s.length; i++) {
console.log(s[i]);//循环输出hello
}
console.log(i); // 5(这里拿到了for循环中i的值)
let实际上为JavaScript新增了块级作用域,而且ES6允许块级作用域的任意嵌套
每一层都是一个单独的作用域,每层作用域互相隔离,内层作用域可以定义
外层作用于的同名变量。如下
{
{
{
{
let insane = 'Hello World';
{let insane = 'Hello World'}
}}}};
const命令
声明
const声明一个只读的常量,一旦声明了就不能修改。
也就是说你const声明的是时候就必须要赋值,当然只声明不赋值会报错。
const a = 1;//声明一个只读的变量a
console.log(a);//1
a=3;//报错
const的作用域与lei命令相同,只在声明所在的块级作用域内有效。
const命令声明的常量也是不提升的,同样存在暂时性死区,只能在声明的位置后面使用。
const命令声明的常量,也不可重复声明(基本都和let一样,这里就不举例子了)
本质
const实际上保证的并不是变量的值不得改动。而是指向的那个内存地址所保存的数据不得改动。
const a = [];
a.push('Hello'); // 可执行
a.length = 0; // 可执行
a = ['Dave']; // 报错
如上,常量a是一个数组,这个数组本生就是可写的,但是将另一个数组赋值给a就会报错。
也就是说不能改变他的地址,但是可以为其添加新的属性。(如果真想将对象冻结应该使用Objec.freeze方法)
顶层对象的属性
顶层对象在浏览器环境指的是window对象,在Node指的是global对象。
ES6中为了保持兼容var命令和function命令声明的全局变量,依旧是顶层对象的属性。
let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性。
从ES6开始全局变量将逐步与顶层对象的属性脱钩。
var a = 1;//全局变量a由var命令声明,所以它是顶层对象的属性
window.a // 1
let b = 1;//全局变量b由let命令声明,所以它不是顶层对象的属性
window.b // undefined
转载于//www.cnblogs.com/knade/p/10949573.html
还没有评论,来说两句吧...