1.块作用域语法(Syntax Block scoping)
JavaScript 一直被函数作用域所限制,这就是为什么将整个 JavaScript 文件包装在一个空的立即调用函数表达式(IIFE) 中的原因。这样做是为了隔离文件中的所有变量,所以不会引起变量冲突。
现在,我们有块作用域和两个绑定到块的新变量声明。
let 声明
是块作用域,可以在不影响外部变量的情况下声明具有相同名称的新变量。
var a = 'aa' ; { let a = 5; console.log(a) // 5 } console.log(a) // aa
因为它绑定到一个块作用域中,它解决了这个经典的面试题:“输出是什么,如何让它按照你的期望工作?
for (let i = 1; i < 5; i++){ setTimeout(() => { console.log(i); }, 1000); } //输出1,2,3,4
var
和 let
之间的另一个区别是 let
不会像 var
一样被提升。
{ console.log(a); // undefined console.log(b); // ReferenceError var a = 'car'; let b = 5; }
const 声明
如果你想要在 JavaScript 中声明一个常量变量,以前的惯例可以用块大写来命名变量。但是,这不会保证变量的安全 – 它只是让其他开发人员知道它是一个常量,不应该更改,现在我们可以使用 const
来声明。
分为2中:1.申明的基本数据类型的变量,不能进行值的修改
{ const c = "tree"; console.log(c); // tree c = 46; // TypeError! }
2.引用类型的变量,表示引用的地址不变,对象可以被修改
{ const d = [1, 2, 3, 4]; const dave = { name: 'David Jones', age: 32}; d.push(5); dave.job = "salesman"; console.log(d); // [1, 2, 3, 4, 5] console.log(dave); // { age: 32, job: "salesman", name: 'David Jones'} }
块作用域中函数的问题
函数声明现在被指定为绑定到块作用域中。
{ bar(); // works function bar() { /* do something */ } } bar(); // doesn't work
if ( something) { function baz() { console.log('I passed') } } else { function baz() { console.log('I didn\'t pass') } } baz();
// ES6 之前,这两个函数声明都会被提升,不管 something
是什么,结果就是 'I didn\'t pass'
。 现在我们得到'ReferenceError'
(引用错误),因为 baz
总是受到块作用域的约束。