1,var 声明与变量提升 (Var Declarations and Hoisting)
使用 var 关键字声明的变量,不论在何处都会被视作在函数级作用域内顶部的位置发生(如
果不包含在函数内则为全局作用域内) 什么是变量提升? 看看下面一段代码
function getValue(condition) {
if (condition) {
var value = "blue";
// 其它代码
return value;
} else {
// value 可以被访问到,其值为 undefined
return null;
}
// 这里也可以访问到 value,值仍为 undefined
}
经过变量提升之后函数变为了:
function getValue(condition) {
var value;
if (condition) {
var value = "blue";
return value;
} else {
return null;
}
}
可以看到变量的声明被提升至顶部,但是初始化的位置并没有改变
2,let声明
为了解决var带来的问题,ECMAScript 6 引入了块级作用域的概念,块级作用域可在下面两种情况创建:
let 声明不会将变量提升至当前作用域的顶部
function getValue(condition) {
if (condition) {
let value = "blue";
// 其它代码
return value;
} else {
// value 并不存在(无法访问)
return null;
}
// 这里 value 也不存在
}
var a = 2;
var a = 3; //可以,会覆盖上面a的值
var count = 30;
let count = 40; // 不可以,语法错误
3,const声明
const声明的变量会被视为常量,这意味着它们不能再次被赋值。由于这个原因,所有的 const 声明的变量都必须在声明处初始化。
// 合法的声明
const maxItems = 30;
// 语法错误:未初始化
const name;
const 声明 vs let 声明
1, const 和 let 都是块级声明,意味着执行流跳出声明所在的代码块后就没有办法在访问它们,
同样 const 变量也不会被提升
2, 另一处和 let 相同的地方是,const 也不能对已存在的标识符重复定义
var message = "Hello!";
let age = 25;
// 下面每条语句都会抛出错误
const message = "Goodbye!";
const age = 30;
const 变量的值如果是个对象,那么这个对象本身可以被修改。const 声明只是阻止变量和值的再次绑定而不是值本身的修改
const person = {
name: "Nicholas"
};
// 正常
person.name = "Greg";
// 抛出错误
person = {
name: "Greg"
};
4,全局块级绑定(Global Block Bindings)
let 与 const 另一处不同体现在全局作用域上。当在全局作用域内使用 var 声明时会创建一个全局变量,同时也会被挂载到全局对象window身上。这意味着全局对象的
属性可能会意外地被重写覆盖
var RegExp = "Hello!";
console.log(window.RegExp); // "Hello!"
var ncz = "Hi!";
console.log(window.ncz); // "Hi!"
如果你在全局作用域内使用 let 或 const,那么绑定就会发生在全局作用域内,但是不会向全局对象内部添加任何属性。
let RegExp = "Hello!";
console.log(RegExp); // "Hello!"
console.log(window.RegExp === RegExp); // false
const ncz = "Hi!";
console.log(ncz); // "Hi!"
console.log("ncz" in window); // false