ECMAScript 变量是涣散类型的,意思是变量能够用于保留任何类型的数据。每个变量只不过是一个用于保留任意值的命令占位符。在 ECMAScript 6 之前,申明变量应用 var
关键字,ECMAScript 6 新增了 const
和 let
关键字用以申明变量。
var
应用 var
关键字申明变量:
var msg; // 不初始化时,变量保留一个非凡值 undefined
var msg = "Hello"; // 初始化
msg = 3.14; // 能够扭转保留的值和值的类型,但不举荐
作用域
var
申明的变量的作用域是函数作用域,在函数退出时销毁变量:
function test() {var msg = "Hello";}
test();
console.log(msg); // ReferenceError: msg is not defined
然而省略 var
会创立全局变量:
function test() {msg = "Hello";}
test();
console.log(msg); // Hello
但这样操作会使得全局变量很难保护,不举荐这样做。
var 申明晋升
在 var
申明变量之前调用变量不会报错,因为 var
申明的变量会主动晋升到函数作用域顶部:
function test() {console.log(name);
var name = "小明";
}
test(); // undefined
let
let
跟 var
的作用差不多,但也有着十分重要的区别。最次要的区别是:let
申明变量的作用域是块作用域,var
申明变量的作用域是函数作用域。
function varScope() {if (true) {
var name = "var name";
console.log(name); // var name
}
console.log(name); // var name
}
function letScope() {if (true) {
let name = "let name";
console.log(name); // let name
}
console.log(name); // ReferenceError: name is not defined
}
从下面的例子中晓得,let
关键字申明变量的作用域仅限于块外部。块作用域是函数作用域的子集,实用于 var
的作用域限度同样也实用于 let
。
反复申明
let
不容许同一个块作用域中呈现 反复申明 。呈现时会导致报错:
function varScope() {
var name = "var name";
var name = "var name";
}
function letScope() {
let name = "let name";
let name = "let name"; // SyntaxError: Identifier 'name' has already been declared
}
然而,嵌套应用雷同标识符相当于创立一个新的块作用域,因而,雷同的标识符不会报错,这是因为同一个块中没有反复申明:
function letScope() {
let name = "let name 1";
if (true) {
let name = "let name 2";
console.log(name); // let name 2
}
console.log(name); // let name 1
}
暂时性死区
var
申明的变量的初始值是 undefined
。然而 let
与 var
不同,通过 let
申明的变量不会在作用域中被晋升。直到申明被执行时才初始化,初始化前拜访变量会导致 ReferenceError
,let
申明变量之前的执行霎时被称为“暂时性死区”
let 与 var 的另一个重要的区别,就是 let 申明的变量不会在作用域中被晋升。
function deadZone() {console.log(varname); // undefined
console.log(letname); // ReferenceError
let letname = "let name";
var varname = "var name";
}
全局申明
var
在 全局作用域 中申明的变量会成为 window
对象的属性;而 let
申明的变量不会称为 window
对象的属性。
var varname = 'var name';
console.log(window.name); // 'var name'
let letname = "let name";
console.log(window.letname); // undefined
但 let
申明依然是在全局作用域中产生的,相应变量会在页面的申明周期内存续。因而,为了防止 SyntaxError
,必须确保页面不会反复申明同一个变量。
const
const
申明的变量也是块作用域,与 let
基本相同,只是 const
申明变量时必须同时初始化变量。申明的变量的值是只读的,批改 const
申明的变量会导致运行时谬误。
// 申明常量要有一个初始值
const name; // SyntaxError: Missing initializer in const declaration
// 块作用域
const name = "const name 1";
if (true) {
const name = "const name 2";
console.log(name); // const name 2
}
console.log(name); // const name 1
name = "const name 2"; // TypeError: Assignment to constant variable.
// 尝试从新申明
const name = "const name 3"; // SyntaxError: Identifier 'name' has already been declared
const
也能够申明对象和数组。当申明的变量是一个对象时,不批改对象援用,而是批改对象外部的属性不违反 const
的限度。
const student = {};
student.name = "小明";
const
本质上保留的并不是变量的值不得改变,而是变量指向的内存地址不得改变。
在 for
循环中不能应用 const
申明变量,因为迭代时变量会自增就会抛出 TypeError
谬误:
for (const i = 0; i < 10; i++) {}
// TypeError: Assignment to constant variable.
然而,在 for-in
或 for-of
循环中应用不会报错。
for (const key in {name: "小明", age: 24}) {console.log(key); // name, age
}
for (const value of ["name", "age", "id", "sex"]) {console.log(value); // name, age, id, sex
}
总结
var
申明变量带来了许多问题,ECMAScript 6 减少的 let
和 const
对语言更准确地申明作用域和语义提供了更好的反对,晋升了代码品质。新增了两个关键字后,以不再须要 var
来申明变量,这样使得变量有明确的作用域、申明地位,以及不变的值。但申明变量时最好应用 const
,这样使得变量在浏览器运行时强制放弃不变。只在提前晓得将来会有批改时,再应用 let
。
更多内容请关注公众号「 海人为记 」