字符串模板和插值多年来,ECMAScript 开发人员使用了一些难看的字符串串联来将变量成员放入字符串中,比如:
var message = "The user " + user.firstName + " " + user.lastName +
" cannot be " + action + " because " + validationError;
|
尽管此策略不是 JavaScript 中最大的错误来源,但它容易出错,更别提难以读取了。在适用性方面,它使得 JavaScript 落后于支持字符串插值的语言。为了不继续落后,ECMAScript 6 引入了重音符字符串字面量(backtick string literal)。这个字面量允许使用重音符 (`) 表示支持字符串插值的字符串字面量。
var message = `The user ${user.firstName} ${user.lastName} cannot be
${action} because ${validationError}`;
|
在 be 和 ${action} 之间使用硬换行符,是因为重音符字符串也是 “多行字面量”。这意味着字符串中保留了空格,所以上面的消息将显示在两行上。它将在 “be” 后断开,然后在继续之前显示两个空格(因为代码缩进了两个空格)。
如果您想知道:重音符通常隐藏在美式键盘的左上角,位于波浪字符 (~) 下方。
当然,不幸的是 ECMAScript 6 需要引入一种新的字符串字面量,而不是简单地支持在现有的单引号或双引号字符串中进行插入。但是,支持插值的向后兼容性意义非常大。这可能是最佳解决方案。随着时间的推移,我们可以预期大部分字符串字面量都将变成重音符字符串。
变量声明:let 和 constECMAScript 在过去允许程序员使用变量而不声明它们。但是,这么做会隐式地让它们成为全局变量,这被认为是一种不可取的行为。(除非它被称为 “单例模式”,进而被视为一种模式。)为了解决此问题,JavaScript 程序员开始使用 var 声明样式来在使用前声明变量。
不同于其他许多语言,ECMAScript 从来没有出现特定变量被重新声明多次的问题。因此,在守旧的 ECMAScript 中,您可以编写以下没有用的代码:
var msg = "Howdy";
var msg = "Hello there"; // acceptable, just reassigns
|
第二个声明绝不会导致错误。在上面的情况中,会向最初的变量重新分配新值。这是一个细微错误来源,C/C++/Java/C# 开发人员对此感到很奇怪。除此之外,ECMAScript 从来没有提供一个工具来创建与 Java 中的 final 或 C# 或 C++ 中的 const 类似的不可变变量。
ECMAScript 6 解决了所有这些问题:首先,它建议将 var 替换为 let,let 不可以重新声明。除此之外,let 的操作与 var 完全相同:
var msg = "Howdy";
var msg = "Hello there"; // acceptable, just reassigns
let message = `This is your message.`;
let message = `This is another message.`; // ERROR!
|
在变量声明中使用 const,满足了对不可变性的需求。完成设置之后,使用 const 声明的变量绝对不能修改:
const message = `This is your message.`;
message = `This is your second message.`; // ERROR!
|
尽管使用 const 声明的变量不能更改其值,但该变量指向的 object 不是常量,所以它仍是可修改的:
const user = request.user;
user = new User(); // ERROR!
user.authorized = true; // acceptable, changes a property
|
因此,我的建议是首先使用 const。如果确实需要修改该变量,始终可以将声明更改为 let。
代码块范围谈到变量声明,令许多 ECMAScript 开发人员感到奇怪的是声明的变量没有绑定到声明它们的 “代码块”。它们被绑定到函数。这是一个函数范围变量的示例:
function bar() {
var i = 10;
while (i > 0) {
var j = 1;
while (j > 0) {
var i = 1; // This is the same i as above
j--;
i--;
}
}
}
|
重用变量名绝不正确,但在包含多个不同的非嵌套循环的长方法中,这是一个很容易犯的错误。
上面的函数将进入嵌套循环一次,因为 i 的第二个 “声明” 仅将值 1 赋给它。或许这不符合程序员的意图,但其中已考虑到了所有方面。
从 ECMAScript 6 开始,使用 let 和 const 声明的变量都具有代码块范围,所以在当前表达式代码块结束时,而不是函数结束时,它们将超出范围。重写前面的代码,使用 let 代替 var,这将得到预期的行为:
function bar() {
let i = 10;
while (i > 0) {
let j = 1;
while (j > 0) {
let i = 1; // Different i
j--;
i--;
}
} // This loop will execute 10 times, as intended
}
|
更广义地讲,代码块范围意味着使用 let 和 const 声明的变量的行为将与其他基于 C 的语言中的变量相同。与 ECMAScript 目前为止管理变量的奇怪方式相比,这是一大改进。 |