1
0
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:
Ruan Yifeng 2015-07-31 20:46:08 +08:00
parent f790a5ea17
commit 634ab7c5a2
3 changed files with 127 additions and 8 deletions

View File

@ -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`,即实质上执行了下面的代码。

View File

@ -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中只要使用尾递归就不会发生栈溢出相对节省内存。
目前,只有开启严格模式,尾调用优化才会生效。
### 递归函数的改写

View File

@ -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");