let 和 const
let
{
let a = 1; // <-- 只在 let 所在的代码块中有效
var b = 2;
}
console.log(a); // Uncaught ReferenceError: a is not defined
console.log(b); // 2
for 循环
// var
var fnList = [];
for (var i = 0; i < 10; i++){
fnList[i] = () => {
console.log(i);
}
}
fnList.forEach(fn => fn()); // 打印出 10 个 10
// let
var fnList2 = [];
for (let j = 0; j < 10; j++) {
fnList2[j] = () => {
console.log(j);
}
}
fnList2.forEach(fn => fn()); // 0 1 2 3 4 5 6 7 8 9
不存在变量提升
console.log(a); // undefined
var a = 1;
console.log(b); // Uncaught ReferenceError: b is not defined
let b = 2;
暂时性死区
let a = 1;
if (true) {
a = 2; // Uncaught ReferenceError: e is not defined
let a;
}
typeof x; // Uncaught ReferenceError: x is not defined <-- typeof 不再是百分百安全的操作符
let x;
隐蔽死区
function bar(x = y, y = 2) { // Uncaught ReferenceError: y is not defined <-- x = y 此时 y 还没声明,会有暂时性死区
return [x, y];
}
bar();
不允许重复声明
function func() {
let a = 1;
var a = 2;
}
// Uncaught SyntaxError: Identifier 'a' has already been declared
function func2() {
let a = 1;
let a = 2;
}
// Uncaught SyntaxError: Identifier 'a' has already been declared
不能在函数内部重新声明参数
function func(arg) {
let arg;
}
// Uncaught SyntaxError: Identifier 'arg' has already been declared
// 不报错
function func2(arg) {
{
let arg;
}
}
func2();
块级作用域
ES5 只有全局作用域和函数作用域。
1、内层变量会覆盖外层变量
var a = new Date();
function f() {
console.log(a);
if (false) {
var a = 'Hello a.';
}
}
f(); // undefined
2、用来计数的循环变量泄露为全局变量
var s = 'Hello';
for (var i = 0; i < s.length; i++) {
console.log(s[i]);
}
console.log(i); // 5
ES6 的块级作用域
function fn() {
let a = 1;
if (true) {
let a = 2;
}
console.log(a);
}
fn(); // 1
块级作用域和函数声明
ES5 规定函数只能在顶层作用域和函数作用域中声明。
// ES5 环境中
function f() {
console.log('I am outside.');
}
(function() {
if (false) {
function f() {
console.log('I am inside.');
}
}
f(); // I am inside.
})();
// ES6 环境中 会报错
function f() {
console.log('I am outside.');
}
(function() {
if (false) {
function f() {
console.log('I am inside.');
}
}
f(); // Uncaught TypeError: f is not a function
})();
应避免在块级作用域中声明函数,如果需要,可写成函数表达式。
{
let a = 'a';
function f() {
console.log(a);
}
}
f(); // a
{
let a = 'a';
const f2 = function() {
console.log(a);
}
}
f2(); // Uncaught ReferenceError: f2 is not defined
ES6 的块级作用域必须有大括号。
if (true) let a = 1; // Uncaught SyntaxError: Lexical declaration cannot appear in a single-statement context
// 不报错
if (true) {
let a = 1;
}
const
const 声明一个只读的常量,声明后值不能改变。
const 声明的常量,只是指向的地址不能改变,但是对于符合类型的数据,是可以改变里面的属性的。
const a = {};
a.name = 'a';
a.age = 20;
console.log(a); // {name: "a", age: 20}
a = {}; // Uncaught TypeError: Assignment to constant variable
要冻结对象,可以用 Object.freeze
正常模式下,修改对象属性不会生效。
const a = {};
Object.freeze(a);
a.name = 'a';
console.log(a); // {}
严格模式下,修改对象属性会报错。
'use strict';
const a = {};
Object.freeze(a);
a.name = 'a'; // Uncaught TypeError: Cannot add property name, object is not extensible
顶层对象的属性
顶层对象,在浏览器中指的 window 对象,在 Node 中指的是 global 对象。在 ES5 中,顶层对象的属性和全局变量是等价的。
window.a = 1;
console.log(a); // 1
a = 2;
console.log(window.a); // 2