mirror of
https://github.com/ruanyf/es6tutorial.git
synced 2025-05-28 21:32:20 +00:00
edit docs/class
This commit is contained in:
parent
f790a5ea17
commit
634ab7c5a2
@ -436,9 +436,9 @@ B.__proto__ === A // true
|
||||
B.prototype.__proto__ === A.prototype // true
|
||||
```
|
||||
|
||||
上面代码中,子类A的`__proto__`属性指向父类B,子类A的prototype属性的__proto__属性指向父类B的prototype属性。
|
||||
上面代码中,子类B的`__proto__`属性指向父类A,子类B的prototype属性的__proto__属性指向父类A的prototype属性。
|
||||
|
||||
这两条继承链,可以这样理解:作为一个对象,子类(B)的原型(`__proto__属性`)是父类(A);作为一个构造函数,子类(B)的原型(prototype属性)是父类的实例。
|
||||
这两条继承链,可以这样理解:作为一个对象,子类(B)的原型(`__proto__`属性)是父类(A);作为一个构造函数,子类(B)的原型(prototype属性)是父类的实例。
|
||||
|
||||
```javascript
|
||||
B.prototype = new A();
|
||||
@ -477,7 +477,7 @@ class A extends null {
|
||||
}
|
||||
|
||||
A.__proto__ === Function.prototype // true
|
||||
A.prototype.__proto__ === null // true
|
||||
A.prototype.__proto__ === undefined // true
|
||||
```
|
||||
|
||||
这种情况与第二种情况非常像。A也是一个普通函数,所以直接继承`Funciton.prototype`。但是,A调用后返回的对象不继承任何方法,所以它的`__proto__`指向`Function.prototype`,即实质上执行了下面的代码。
|
||||
|
@ -694,7 +694,7 @@ function f(x){
|
||||
}
|
||||
```
|
||||
|
||||
上面代码中,情况一是调用函数g之后,还有别的操作,所以不属于尾调用,即使语义完全一样。情况二也属于调用后还有操作,即使写在一行内。情况三等同于下面的代码。
|
||||
上面代码中,情况一是调用函数g之后,还有赋值操作,所以不属于尾调用,即使语义完全一样。情况二也属于调用后还有操作,即使写在一行内。情况三等同于下面的代码。
|
||||
|
||||
```javascript
|
||||
function f(x){
|
||||
@ -746,6 +746,20 @@ g(3);
|
||||
|
||||
这就叫做“尾调用优化”(Tail call optimization),即只保留内层函数的调用帧。如果所有函数都是尾调用,那么完全可以做到每次执行时,调用帧只有一项,这将大大节省内存。这就是“尾调用优化”的意义。
|
||||
|
||||
注意,只有不再用到外层函数的内部变量,内层函数的调用帧才会取代外层函数的调用帧,否则就无法进行“尾调用优化”。
|
||||
|
||||
```javascript
|
||||
function addOne(a){
|
||||
var one = 1;
|
||||
function inner(b){
|
||||
return b + one;
|
||||
}
|
||||
return inner(a);
|
||||
}
|
||||
```
|
||||
|
||||
上面的函数不会进行尾调用优化,因为内层函数inner用到了,外层函数addOne的内部变量one。
|
||||
|
||||
### 尾递归
|
||||
|
||||
函数调用自身,称为递归。如果尾调用自身,就称为尾递归。
|
||||
@ -774,7 +788,9 @@ function factorial(n, total) {
|
||||
factorial(5, 1) // 120
|
||||
```
|
||||
|
||||
由此可见,“尾调用优化”对递归操作意义重大,所以一些函数式编程语言将其写入了语言规格。ES6也是如此,第一次明确规定,所有 ECMAScript 的实现,都必须部署“尾调用优化”。这就是说,在 ES6 中,只要使用尾递归,就不会发生栈溢出,相对节省内存。
|
||||
由此可见,“尾调用优化”对递归操作意义重大,所以一些函数式编程语言将其写入了语言规格。ES6也是如此,第一次明确规定,所有ECMAScript的实现,都必须部署“尾调用优化”。这就是说,在ES6中,只要使用尾递归,就不会发生栈溢出,相对节省内存。
|
||||
|
||||
目前,只有开启严格模式,尾调用优化才会生效。
|
||||
|
||||
### 递归函数的改写
|
||||
|
||||
|
109
docs/string.md
109
docs/string.md
@ -127,6 +127,8 @@ ES6对这一点做出了改进,只要将码点放入大括号,就能正确
|
||||
|
||||
ES6对正则表达式添加了u修饰符,用来正确处理大于\uFFFF的Unicode字符。
|
||||
|
||||
一旦加上u修饰符号,就会修改下面这些正则表达式的行为。
|
||||
|
||||
**(1)点字符**
|
||||
|
||||
点(.)字符在正则表达式中,解释为除了换行以外的任意单个字符。对于码点大于0xFFFF的Unicode字符,点字符不能识别,必须加上u修饰符。
|
||||
@ -300,7 +302,9 @@ repeat()返回一个新字符串,表示将原字符串重复n次。
|
||||
|
||||
## 正则表达式的y修饰符
|
||||
|
||||
除了u修饰符,ES6还为正则表达式添加了y修饰符,叫做“粘连”(sticky)修饰符。它的作用与g修饰符类似,也是全局匹配,后一次匹配都从上一次匹配成功的下一个位置开始,不同之处在于,g修饰符只要剩余位置中存在匹配就可,而y修饰符确保匹配必须从剩余的第一个位置开始,这也就是“粘连”的涵义。
|
||||
除了u修饰符,ES6还为正则表达式添加了y修饰符,叫做“粘连”(sticky)修饰符。
|
||||
|
||||
y修饰符的作用与g修饰符类似,也是全局匹配,后一次匹配都从上一次匹配成功的下一个位置开始。不同之处在于,g修饰符只要剩余位置中存在匹配就可,而y修饰符确保匹配必须从剩余的第一个位置开始,这也就是“粘连”的涵义。
|
||||
|
||||
```javascript
|
||||
var s = "aaa_aa_a";
|
||||
@ -328,6 +332,40 @@ r.exec(s) // ["aa_"]
|
||||
|
||||
上面代码每次匹配,都是从剩余字符串的头部开始。
|
||||
|
||||
使用lastIndex属性,可以更好地说明y修饰符。
|
||||
|
||||
```javascript
|
||||
const REGEX = /a/g;
|
||||
|
||||
REGEX.lastIndex = 2; // 指定从第三个位置y开始搜索
|
||||
const match = REGEX.exec('xaya');
|
||||
|
||||
match.index
|
||||
// 3
|
||||
REGEX.lastIndex
|
||||
// 4
|
||||
REGEX.exec('xaxa')
|
||||
// null
|
||||
```
|
||||
|
||||
上面代码中,lastIndex属性指定每次搜索的开始位置,g修饰符从这个位置开始向后搜索,直到发现匹配为止。
|
||||
|
||||
y修饰符同样遵守lastIndex属性,但是要求必须在lastIndex指定的位置发现匹配。
|
||||
|
||||
```javascript
|
||||
const REGEX = /a/y;
|
||||
|
||||
// 第三个位置y不匹配
|
||||
REGEX.lastIndex = 2;
|
||||
console.log(REGEX.exec('xaya')); // null
|
||||
|
||||
// 第四个位置出现匹配
|
||||
REGEX.lastIndex = 3;
|
||||
const match = REGEX.exec('xaxa');
|
||||
match.index // 3
|
||||
REGEX.lastIndex // 4
|
||||
```
|
||||
|
||||
进一步说,y修饰符号隐含了头部匹配的标志ˆ。
|
||||
|
||||
```javascript
|
||||
@ -337,6 +375,32 @@ r.exec(s) // ["aa_"]
|
||||
|
||||
上面代码由于不能保证头部匹配,所以返回null。y修饰符的设计本意,就是让头部匹配的标志ˆ在全局匹配中都有效。
|
||||
|
||||
在split方法中使用y修饰符,原字符串必须以分隔符开头。
|
||||
|
||||
```javascript
|
||||
// 没有找到匹配
|
||||
'x##'.split(/#/y)
|
||||
// [ 'x##' ]
|
||||
|
||||
// 找到两个匹配
|
||||
'##x'.split(/#/y)
|
||||
// [ '', '', 'x' ]
|
||||
```
|
||||
|
||||
后续的分隔符只有紧跟前面的分隔符,才会被识别。
|
||||
|
||||
```javascript
|
||||
'#x#'.split(/#/y)
|
||||
// [ '', 'x#' ]
|
||||
|
||||
'##'.split(/#/y)
|
||||
// [ '', '', '' ]
|
||||
```
|
||||
|
||||
如果同时使用g修饰符和y修饰符,则y修饰符覆盖g修饰符。
|
||||
|
||||
## 正则表达式的sticky属性
|
||||
|
||||
与y修饰符相匹配,ES6的正则对象多了sticky属性,表示是否设置了y修饰符。
|
||||
|
||||
```javascript
|
||||
@ -344,7 +408,46 @@ var r = /hello\d/y;
|
||||
r.sticky // true
|
||||
```
|
||||
|
||||
## Regexp.escape()
|
||||
## 正则表达式的flags属性
|
||||
|
||||
ES6为正则表达式新增了flags属性,会返回正则表达式的修饰符。
|
||||
|
||||
```javascript
|
||||
// ES5的source属性
|
||||
// 返回正则表达式的正文
|
||||
/abc/ig.source
|
||||
// "abc"
|
||||
|
||||
// ES6的flags属性
|
||||
// 返回正则表达式的修饰符
|
||||
/abc/ig.flags
|
||||
// 'gi'
|
||||
```
|
||||
|
||||
## RegExp构造函数
|
||||
|
||||
在ES5中,RegExp构造函数只能接受字符串作为参数。
|
||||
|
||||
```javascript
|
||||
var regex = new RegExp("xyz", "i");
|
||||
// 等价于
|
||||
var regex = /xyz/i;
|
||||
```
|
||||
|
||||
ES6允许RegExp构造函数接受正则表达式作为参数,这时会返回一个原有正则表达式的拷贝。
|
||||
|
||||
```javascript
|
||||
var regex = new RegExp(/xyz/i);
|
||||
```
|
||||
|
||||
如果使用RegExp构造函数的第二个参数指定修饰符,则会修改原有的正则表达式。
|
||||
|
||||
```javascript
|
||||
new RegExp(/abc/ig, 'i').flags
|
||||
// "i"
|
||||
```
|
||||
|
||||
## RegExp.escape()
|
||||
|
||||
字符串必须转义,才能作为正则模式。
|
||||
|
||||
@ -360,7 +463,7 @@ escapeRegExp(str)
|
||||
|
||||
上面代码中,str是一个正常字符串,必须使用反斜杠对其中的特殊字符转义,才能用来作为一个正则匹配的模式。
|
||||
|
||||
已经有[提议](https://esdiscuss.org/topic/regexp-escape)将这个需求标准化,作为[`Regexp.escape()`](https://github.com/benjamingr/RexExp.escape),放入ES7。
|
||||
已经有[提议](https://esdiscuss.org/topic/regexp-escape)将这个需求标准化,作为RegExp对象的静态方法[`RegExp.escape()`](https://github.com/benjamingr/RexExp.escape),放入ES7。
|
||||
|
||||
```javascript
|
||||
RegExp.escape("The Quick Brown Fox");
|
||||
|
Loading…
x
Reference in New Issue
Block a user