在过去几年里,JavaScript 有很多的更新。如果你想提升写代码的能力,这些更新将会对你有非常大的帮助。
对于程序员来说,了解这门语言的最新发展是非常重要的。它能使你跟上最新趋势,提高代码质量,在工作中出类拔萃,从而进一步提升你的薪资待遇。
特别地,如果你想学习像 React 、Angular 或 Vue 这样的框架,你必须掌握这些最新的特性。
最近,JavaScript 增加了许多有用的功能,比如Nullish coalescing operator, optional chaining, Promises, async/await, ES6 destructuring,等等。
那么现在,我们将探讨每个 JavaScript 开发者都应该知道的概念。
JavaScript 中的 Let 和 const
在 ES6 之前,JavaScript 使用 var 关键字来声明变量,var 只有全局作用域和函数作用域,所谓全局作用域就是在代码的任何位置都能访问 var 声明的变量,而函数作用域在变量声明的当前函数内部访问变量。此时是没有块级作用域的。
随着 let 和 const 这两个关键字的添加,JS 增加了块级作用域的概念。
如何在 JavaScript 中使用 let
当我们在用 let 声明变量时,用于声明一次之后就不能再以相同的名称重新声明它。
// ES5 Code
var value = 10;
console.log(value); // 10
var value = "hello";
console.log(value); // hello
var value = 30;
console.log(value); // 30
如上所示,我们多次使用 var 关键字重新声明了变量值。
在 ES6 之前,我们可以使用 var 重新声明之前已经声明过的变量,这就会导致了一个问题:如果我们在不知情的情况下,在其他地方重新声明了该变量,很有可能会覆盖原先变量的值,造成一些难以调试的问题。
所以,Let 解决很好地解决此问题。当你使用 let 重新声明变量值时,将会报错。
// ES6 Code
let value = 10;
console.log(value); // 10
let value = "hello"; // Uncaught SyntaxError: Identifier 'value' has already been declared
但是,以下代码是合法的:
// ES6 Code
let value = 10;
console.log(value); // 10
value = "hello";
console.log(value); // hello
我们发现上面的代码看起来没什么问题,是因为我们重新给 value 变量赋了一个新值,但是并没有重新声明。
我们来看下下面的代码:
// ES5 Code
var isValid = true;
if(isValid) {
var number = 10;
console.log('inside:', number); // inside: 10
}
console.log('outside:', number); // outside: 10
如上所示,在使用 var 声明变量时,可以在 if 块之外访问该变量。
而使用 let 声明的 number 变量只能在 if 块内访问,如果在 if 块外访问将会报错。
我们来看下接下来的代码
// ES6 Code
let isValid = true;
if(isValid) {
let number = 10;
console.log('inside:', number); // inside: 10
}
console.log('outside:', number); // Uncaught ReferenceError: number is not defined
如上述代码所示,使用 let 分别在 if 块内、if 块外声明了 number 变量。在 if 块外,number 无法被访问,因此会出现引用错误。
但是,如果变量 number 在 if 块外已经声明,将会出现下面的结果。
// ES6 Code
let isValid = true;
let number = 20;
if(isValid) {
let number = 10;
console.log('inside:', number); // inside: 10
}
console.log('outside:', number); // outside: 20
现在在单独的范围内有两个 number 变量。在 if 块外,number 的值为 20 。
// ES5 Code
for(var i = 0; i < 10; i++){
console.log(i);
}
console.log('outside:', i); // 10
当使用 var 关键字时,i 在 for 循环之外也可以访问到。
// ES6 Code
for(let i = 0; i < 10; i++){
console.log(i);
}
console.log('outside:', i); // Uncaught ReferenceError: i is not defined
而使用 let 关键字时,在 for 循环外部是不可访问的。
因此,正如上述示例代码所示,let 声明的变量只能在块内部可用,而在块外部不可访问。
我们可以使用一对大括号创建一个块,如下:
let i = 10;
{
let i = 20;
console.log('inside:', i); // inside: 20
i = 30;
console.log('i again:', i); // i again: 30
}
console.log('outside:', i); // outside: 10
前面有提到,let 在同一个块中不能重新声明变量,不过可以在另一个块中重新声明。如上代码所示,我们在块内重新声明了 i,并赋值 20,该变量仅可在该块中使用。
在块外,当我们打印变量时,我们得到的是 10 而不是之前分配的值,这是因为块外,内部变变量 i 是不存在的。
如果在块外未声明变量,那么将会报错:
{
let i = 20;
console.log('inside:', i); // inside: 20
i = 30;
console.log('i again:', i); // i again: 30
}
console.log('outside:', i); // Uncaught ReferenceError: i is not defined
如何在 JavaScript 使用 const
const 关键字在块级作用域中的工作方式与 let 关键字完全相同。因此,我们来看下他们的区别。
const 声明的变量为常量,其值是不能改变的。而 let 声明的变量,可以为其赋一个新值,如下所示:
let number = 10;
number = 20;
console.log(number); // 20
但是以下情况,我们不能这样使用 const 。
const number = 10;
number = 20; // Uncaught TypeError: Assignment to constant variable.
我们甚至不能使用 const 像下面一样重新声明。
const number = 20;
console.log(number); // 20
const number = 10; // Uncaught SyntaxError: Identifier 'number' has already been declared
现在,看下面的代码:
const arr = [1, 2, 3, 4];
arr.push(5);
console.log(arr); // [1, 2, 3, 4, 5]
我们说过 const 声明的常量,它的值永远不会改变——但是我们改变了上面的常量数组并没有报错。这是为什么呢?
注意:数组是引用类型,而不是 JavaScript 的基本类型
实际存储在 arr 中的不是数组,而是数组存储的内存位置的引用(地址)。执行 arr.push(5),并没有改变 arr 指向的引用,而是改变了存储在那个引用上的值。
对象也是如此:
const obj = {
name: 'David',
age: 30
};
obj.age = 40;
console.log(obj); // { name: 'David', age: 40 }
这里,我们也没有改变 obj 指向的引用,而是改变了存储在引用的值。
因此,上述的代码将会起作用,但下面的代码是无效的。
const obj = { name: 'David', age: 30 };
const obj1 = { name: 'Mike', age: 40 };
obj = obj1; // Uncaught TypeError: Assignment to constant variable.
这样写会抛出异常,因为我们试图更改 const 变量指向的引用。
因此,在使用 const 时要记住一点:使用 const 声明常量时,不能重新声明,也不能重新赋值。如果声明的常量是引用类型,我们可以更改存储在引用的值。
同理,下面的代码也是无效的。
const arr = [1, 2, 3, 4];
arr = [10, 20, 30]; // Uncaught TypeError: Assignment to constant variable.
总结:
- 关键字 let 和 const 在 JavaScript 中添加块级作用域。
- 当我们将一个变量声明为 let 时,我们不能在同一作用域(函数或块级作用域)中重新定义或重新声明另一个具有相同名称的 let 变量,但是我们可以重新赋值。
- 当我们将一个变量声明为 const 时,我们不能在同一作用域(函数或块级作用域)中重新定义或重新声明具有相同名称的另一个 const 变量。但是,如果变量是引用类型(如数组或对象),我们可以更改存储在该变量中的值。
- fulfilled:表示操作成功完成。
- rejected: 表示操作失败。
- 默认导出:单个文件中只能有一个默认导出