let语法和const语法
let语法
let是 ES6规范中定义 的 用于声明变量的关键字。使用let
声明了变量,那这个变量就有一个块级作用域范围。而块级作用域存在三种代码书写情况(注意:块级作用域出现的前提是进行let变量声明) :
-
独立的一对大括号,两个大括号之间就是变量a的块级作用域的范围:
{ let a = 1; }
-
条件语句,函数声明语句,循环语句等中的一对大括号内就是变量b,c,d的块级作用域的范围:
if(true){ let b = 2; }; function fangFa(){ let c = 3; }; while(true){ let d = 6; };
3.for循环语句中的一对小括号内中的设置循环变量那部分就是一种特殊的块级作用域:
for (let i = 0; i < 3; i++) { let i = 'abc'; console.log(i); }
(1)下面代码中 let i = 0 所在小括号就是变量i的特殊的块级作用域
(2)这个特殊的块级作用域可以说时大括号这个作用域的父作用域
(3)可以看成大括号内的作用域是嵌套在这个特殊作用域中的,也就是多个块级作用域的嵌套
4.块级作用域在多层嵌套时作用域的范围(
注意:因为有了使用let进行变量声明,所以才会有块级作用域的概念
):// 下面的代码中因为只有在第一个if语句中大括号中使用了let进行变量声明, // 所以整个大括号中的所有就是 变量a 的块级作用域 if(true){ let a = '123456'; if(true){ // 这里依然是变量a的块级作用域,所以在第二个if语句大括号中操作 变量 a 会产生效果 a = 'ABCDEF'; } // 控制台打印输出 ‘ABCDEF’ console.log(a); }
5.比较 使用
var
变量的for
循环 和 使用let
变量的for
循环 这两种循环的区别: (1)
var
变量的for
循环:// 下面的代码是现在全局函数中的,且代码中的变量声明都是var // 所以变量 a 和变量 i 都是全局变量 var a = []; // for 循环总的 i++ 一直是在对全局变量进行操作 for (var i = 0; i < 10; i++) { a[i] = function () { // 这里的变量i就是全局变量i,如此在调用本函数的时候就会从全局变量中取值了 console.log(i); }; } // 控制台打印输出 10 // 函数中取全局变量i的值时,全局变量i的值已经是 10 了 a[6]();
(2)
let
变量的for
循环:var a = []; for (let i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } // 控制台打印输出 6 a[6]();
在for循环的小括号中使用了let声明了变量i,且循环体中没有使用到let声明变量,会默认let声明,每次循环都会得到不同的i。
6.块级作用域中,let声明的变量在使用时有三种限制:
(1) 在同一个块级作用域中,不允许重复声明同一个变量名:
function test(x){ let x = 1; } test();
test函数体中使用了 let 声明了 变量 x ,但是在参数中也有一个 x,在解释器执行 test() 方法时,会对参数 x 进行声明变量,此时就和 let 声明的 变量 x 由了冲突,从而报错。
(2) 在块级作用域中,变量进行声明赋值表达式前为暂时性死区:
console.log(foo); // 控制台输出undefined var foo = 2;// 这是一个声明赋值表达式 console.log(bar); // 控制台报错ReferenceError let bar = 2;//这是个声明赋值表达式
(3) 为什么需要块级作用域?
1. 第一种场景,内层变量可能会覆盖外层变量。 2. 第二种场景,用来计数的循环变量泄露为全局变量。
const语法
- const声明一个只读的常量。一旦声明,常量的值就不能改变。
const PI = 3.1415;
PI // 3.1415
PI = 3;
2.const声明的变量不得改变值,这意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值。
const foo; // 对于const来说,只声明不赋值,就会报错。
3.const的作用域与let命令相同:只在声明所在的块级作用域内有效。
if (true) {
const MAX = 5;
}
MAX
- const命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用。
if (true) {
// 代码在常量MAX声明之前就调用,结果报错。
console.log(MAX); // ReferenceError
const MAX = 5;
}
- const声明的常量,也与let一样不可重复声明。
var message = "Hello!";
let age = 25;
// 以下两行都会报错
const message = "Goodbye!";
const age = 30;
6.const
的本质:const
实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的内存地址数据不得改动。如果想将对象进行常亮化的话就得注意了,因为对象中的变量不是常亮。
7.如果真的想将对象冻结,应该使用Object.freeze
方法:
const foo = Object.freeze({});
// 常规模式时,下面一行不起作用;
// 严格模式时,该行会报错
foo.prop = 123;
顶层对象的属性
顶层对象,在浏览器环境指的是window
对象,在 Node 指的是global
对象。
在ES5中定义全局变量的同时,会在顶层对象中声明相同变量名的变量。而在顶层对象中定义了一个变量,那这个变量也就成了全局变量:
window.b = 1;
b; // 1
var a = 2;
window.a; // 2
在ES6中全局变量和顶层对象的属性就会不相关了,var
定义的依然和以前一样,而let、const
等就遵循新规范:
var a = 1;
// 如果在 Node 的 REPL 环境,可以写成 global.a
// 或者采用通用方法,写成 this.a
window.a // 1
let b = 1;
window.b; // undefined
const c = 2;
window.c; // undefined