ideal
第一章:块级绑定
1.1()var声明的是全局变量
(2)let局部变量
(3)const常量,在声明时需进行初始化
const maxItems=30;(有效的常量)
注释:常量声明与let声明一样,都是块级声明。
这意味着常量在声明他们的语句块外部是无法访问的,并且声明也不会被提升
实例:
if(condition){
const maxItems=5;
//其他代码
}
//maxItems 在此处无法访问
2.循环中的块级绑定
第二章:字符串与正则表达式
1.codePointAt() 方法
codePointAt() 方法的返回值一般与 charCodeAt() 相同,除非操作对象并不是 BMP 字符。
text 字符串的第一个字符不是 BMP 字符,因此它占用了两个码元,意味着该字符串的
length 属性是 3 而不是 2 。 charCodeAt() 方法只返回了位置 0 的第一个码元;
function is32Bit(c) {
return c.codePointAt(0) > 0xFFFF;
}
console.log(is32Bit("" )); // true
console.log(is32Bit("a")); // false
2.String.fromCodePoint() 方法
(1)normalize() 方法
(2)正则表达式 u 标志
当一个正则表达式设置了 u 标志时,它的工作模式将切换到针对字符,而不是针对码元。这
意味着正则表达式将不会被字符串中的代理对所混淆,而是会如预期那样工作。例如,研究
以下代码:
var text = "" ;
console.log(text.length); // 2
console.log(/^.$/.test(text)); // false
console.log(/^.$/u.test(text)); // true
正则表达式 /^.$/ 会匹配只包含单个字符的任意输入字符串。当不使用 u 标志时,该正则
表达式只匹配码元,所以不能匹配由两个码元表示的这个日文字符。启用 u 标志后,正则表
达式就会比较字符而不是码元,所以这个日文字符就会被匹配到。
(3)repeat()方法
ES6 还为字符串添加了一个 repeat() 方法,它接受一个参数作为字符串的重复次数,返回
一个将初始字符串重复指定次数的新字符串。例如:
console.log("x".repeat(3)); // "xxx"
console.log("hello".repeat(2)); // "hellohello"
console.log("abc".repeat(4)); // "abcabcabcabc"
此方法比相同目的的其余方法更加方便,在操纵文本时特别有用,尤其是在需要产生缩进的
代码格式化工具中,像这样:
// indent 使用了一定数量的空格
var indent = " ".repeat(4),
indentLevel = 0;
// 每当你增加缩进
var newIndent = indent.repeat(++indentLevel);
第一次调用 repeat() 创建了一个包含四个空格的字符串,而 indentLevel 变量会持续追踪
缩进的级别。此后,你可以仅通过增加 indentLevel 的值来调用 repeat() 方法,便可以改变
空格数量。
(4)正则表达式 y 标志
y 标志影响正则表达式搜索时的粘连( sticky )属性,它表示从正则表达式的 lastIndex 属性值的
位置开始检索字符串中的匹配字符。如果在该位置没有匹配成功,那么正则表达式将停止检
索
(5)复制正则表达式
ar re1 = /ab/i,
// ES5 中会抛出错误, ES6 中可用
re2 = new RegExp(re1, "g");
console.log(re1.toString()); // "/ab/i"
console.log(re2.toString()); // "/ab/g"
console.log(re1.test("ab")); // true
console.log(re2.test("ab")); // true
console.log(re1.test("AB")); // true
console.log(re2.test("AB")); // false
(6)flags属性
function getFlags(re) {
var text = re.toString();
return text.substring(text.lastIndexOf("/") + 1, text.length);
}
// toString() 的输出为 "/ab/g"
var re = /ab/g;
console.log(getFlags(re)); // "g"
此处将正则表达式转换为一个字符串,并返回了最后一个 / 之后的字符,这些字符即为标
志。
(7)模板字面量
(8)基本语法
模板字面量的最简单语法,是使用反引号( ` )来包裹普通字符串,而不是用双引号或单
引号。参考以下例子:
et message = `Hello world!`;
console.log(message); // "Hello world!"
console.log(typeof message); // "string"
console.log(message.length); // 12
在模板字面量中无需对双引号或单引号进行转义。
(9)多行字符串
感谢存在已久的一个语法 bug , JS 的确有一种权宜之计:在换行之前的反斜线( )可以
用于创建多行字符串。这里有个范例:
var message = "Multiline
string";
console.log(message); // "Multiline string"
message 字符串打印输出时不会有换行,因为反斜线被视为续延符号而不是新行的符号。为
了在输出中显示换行,你需要手动包含它:
var message = "Multiline
string";
console.log(message); // "Multiline
// string"
(10)制造替换位
替换位由起始的 ${ 与结束的 } 来界定,之间允许放入任意的 JS 表达式。最简单的替换
位允许你将本地变量直接嵌入到结果字符串中,例如:
let name = "Nicholas",
message = `Hello, ${name}.`;
console.log(message); // "Hello, Nicholas."
替换位 ${name} 会访问本地变量 name ,并将其值插入到 message 字符串中。 message
变量会立即保留该替换位的结果。
(11)标签化模板
定义标签
一个标签( tag )仅是一个函数,它被调用时接收需要处理的模板字面量数据。标签所接收
的数据被划分为独立片段,并且必须将它们组合起来以创建结果。第一个参数是个数组,包
含被 JS 解释过的字面量字符串,随后的参数是每个替换位的解释值。
标签函数的参数一般定义为剩余参数形式,以便更容易处理数据,如下:
function tag(literals, ...substitutions) {
// 返回一个字符串
}
为了更好地理解传递给标签的是什么参数,可研究下例:
let count = 10,
price = 0.25,
message = passthru`${count} items cost $${(count * price).toFixed(2)}.`;
使用模板字面量中的原始值
模板标签也能访问字符串的原始信息,主要指的是可以访问字符在转义之前的形式。获取原
始字符串值的最简单方式是使用内置的 String.raw() 标签。例如:
let message1 = `Multiline
string`,
message2 = String.raw`Multiline
string`;
console.log(message1); // "Multiline
// string"
console.log(message2); // "Multiline\nstring"
此代码中, message1 中的
被解释为一个换行,而 message2 中的
返回了它的原始
形式 "\n" (反斜线与 n 字符)。像这样提取原始字符串信息可以在必要时进行更复杂的
处理。
例如, literals[0] 的
值总是等价于包含字符串原始信息的 literals.raw[0] 的值。知道这些之后,你可以用如下
代码来模拟 String.raw() :
function raw(literals, ...substitutions) {
let result = "";
// 仅使用 substitution 的元素数量来进行循环
for (let i = 0; i < substitutions.length; i++) {
result += literals.raw[i]; // 改为使用原始值
result += substitutions[i];
}
// 添加最后一个字面量
result += literals.raw[literals.length - 1];
return result;
}
let message = raw`Multiline
string`;
console.log(message); // "Multiline\nstring"
console.log(message.length); // 17
这里使用 literals.raw 而非 literals 来输出结果字符串。这意味着任何转义字符(包括
Unicode 代码点的转义)都会以原始的形式返回。当你想在输出的字符串中包含转义字符
时,原始字符串会很有帮助(例如,若想要生成包含代码的文档,那么应当输出如表面看到
那样的实际代码)。
第三章 函数
(1)带参数默认值的函数
ES6 中的参数默认值
ES6 能更容易地为参数提供默认值,它使用了初始化形式,以便在参数未被正式传递进来时
使用。例如:
function makeRequest(url, timeout = 2000, callback = function() {}) {
// 函数的剩余部分
}
此函数只要求第一个参数始终要被传递。其余两个参数则都有默认值,这使得函数体更为小
巧,因为不需要再添加更多代码来检查缺失的参数值。
(2)参数默认值如何影响 arguments 对象
参数默认值的存在触发了 arguments 对象与
具名参数的分离。这是个细微但重要的细节,因为 arguments 对象的使用方式发生了变化。
研究如下代码:
// 非严格模式
function mixArgs(first, second = "b") {
console.log(arguments.length);
console.log(first === arguments[0]);
console.log(second === arguments[1]);
first = "c";
second = "d"
console.log(first === arguments[0]);
console.log(second === arguments[1]);
}
mixArgs("a");
输出:
第三章 函数
46
1
true
false
false
false
本例中 arguments.length 的值为 1 ,因为只给 mixArgs() 传递了一个参数。这也意味着
arguments[1] 的值是 undefined ,符合将单个参数传递给函数时的预期;这同时意味着
first 与 arguments[0] 是相等的。改变 first 和 second 的值不会对 arguments 对象造
成影响,无论是否在严格模式下,所以你可以始终依据 arguments 对象来反映初始调用状
态。
(3)参数默认值表达式
(4)参数默认值的暂时性死区
第一章介绍了 let 与 const 的暂时性死区( TDZ )
(5)使用不具名参数
(6)剩余参数
(6.1)剩余参数的限制条件
剩余参数受到两点限制。一是函数只能有一个剩余参数,并且它必须被放在最后。例如,如
下代码是无法工作的:
// 语法错误:不能在剩余参数后使用具名参数
function pick(object, ...keys, last) {
let result = Object.create(null);
for (let i = 0, len = keys.length; i < len; i++) {
result[keys[i]] = object[keys[i]];
}
return result;
}
此处的 last 跟在了剩余参数 keys 后面,这会导致一个语法错误。
第二个限制是剩余参数不能在对象字面量的 setter 属性中使用,这意味着如下代码同样会导
致语法错误:
let object = {
// 语法错误:不能在 setter 中使用剩余参数
set name(...value) {
// 一些操作
}
};
存在此限制的原因是:对象字面量的 setter 被限定只能使用单个参数;而剩余参数按照定义
是不限制参数数量的,因此它在此处不被许可。
(6.2)剩余参数如何影响 arguments 对象
(7)函数构造器的增强能力
而对剩余参数来说,只需在最后一个参数前添加 ... 即可,就像这样:
var pickFirst = new Function("...args", "return args[0]");
console.log(pickFirst(1, 2)); // 1
此代码创建了一个仅使用剩余参数的函数,让其返回所传入的第一个参数。
默认参数和剩余参数的添加,确保了 Function 构造器拥有与函数声明形式相同的所有能
力。
(8)扩展运算符
ES6 的扩展运算符令这种情况变得简单。无须调用 apply() ,你可以像使用剩余参数那样在
该数组前添加 ... ,并直接将其传递给 Math.max() 。 JS 引擎将会将该数组分割为独立参
数并把它们传递进去,就像这样:
let values = [25, 50, 75, 100]
// 等价于 console.log(Math.max(25, 50, 75, 100));
console.log(Math.max(...values)); // 100
你可以将扩展运算符与其他参数混用。假设你想让 Math.max() 返回的最小值为 0 (以防数
组中混入了负值),你可以将参数 0 单独传入,并继续为其他参数使用扩展运算符,正如下
例:
let values = [-25, -50, -75, -100]
console.log(Math.max(...values, 0)); // 0
(9)ES6 的名称属性-----55页