1
0
mirror of https://github.com/ruanyf/es6tutorial.git synced 2025-05-24 18:32:22 +00:00
This commit is contained in:
ruanyf 2015-08-28 18:51:35 +08:00
parent 965a2dbb49
commit 5a5f9d8d49
7 changed files with 32 additions and 25 deletions

View File

@ -53,7 +53,7 @@ typeof Point // "function"
上面代码表明,类的数据类型就是函数。
构造函数的prototype属性在ES6的“类”上面继续存在。事实上除了constructor方法以外类的方法都定义在类的prototype属性上面。
构造函数的prototype属性在ES6的“类”上面继续存在。事实上类的所有方法都定义在类的prototype属性上面。
```javascript
class Point {
@ -73,11 +73,23 @@ class Point {
// 等同于
Point.prototype = {
constructor(){},
toString(){},
toValue(){}
}
```
在类的实例上面调用方法,其实就是调用原型上的方法。
```javascript
class B {}
let b = new B();
b.constructor === B.prototype.constructor // true
```
上面代码中b是B类的实例它的constructor方法就是B类原型的constructor方法。
由于类的方法除constructor以外都定义在prototype对象上面所以类的新方法可以添加在prototype对象上面。`Object.assign`方法可以很方便地一次向类添加多个方法。
```javascript
@ -419,7 +431,7 @@ cp instanceof Point // true
### 类的prototype属性和\_\_proto\_\_属性
在ES5中,每一个对象都有`__proto__`属性指向对应的构造函数的prototype属性。Class作为构造函数的语法糖同时有prototype属性和`__proto__`属性,因此同时存在两条继承链。
大多数浏览器的ES5实现之中,每一个对象都有`__proto__`属性指向对应的构造函数的prototype属性。Class作为构造函数的语法糖同时有prototype属性和`__proto__`属性,因此同时存在两条继承链。
1子类的`__proto__`属性,表示构造函数的继承,总是指向父类。

View File

@ -150,9 +150,9 @@ for (var f of flat(arr)){
### 与Iterator的关系
上一章说过,任意一个对象的Symbol.iterator属性,等于该对象的遍历器函数,调用该函数会返回该对象的一个遍历器。
上一章说过,任意一个对象的`Symbol.iterator`方法,等于该对象的遍历器函数,调用该函数会返回该对象的一个遍历器。
遍历器本身也是一个对象,它的Symbol.iterator属性执行后,返回自身。
遍历器本身也是一个对象,它的`Symbol.iterator`方法执行后,返回自身。
```javascript
function* gen(){
@ -331,7 +331,7 @@ try {
上面代码之所以只捕获了a是因为函数体外的catch语句块捕获了抛出的a错误以后就不会再继续执行try语句块了。
如果遍历器函数内部没有部署try...catch代码块那么throw方法抛出的错误将被外部try...catch代码块捕获。
如果Generator函数内部没有部署try...catch代码块那么throw方法抛出的错误将被外部try...catch代码块捕获。
```javascript
var g = function* () {
@ -355,7 +355,7 @@ try {
上面代码中遍历器函数g内部没有部署try...catch代码块所以抛出的错误直接被外部catch代码块捕获。
如果遍历器函数内部部署了try...catch代码块那么遍历器的throw方法抛出的错误不影响下一次遍历否则遍历直接终止。
如果Generator函数内部部署了try...catch代码块那么遍历器的throw方法抛出的错误不影响下一次遍历否则遍历直接终止。
```javascript
var gen = function* gen(){
@ -374,7 +374,7 @@ try {
// hello
```
上面代码只输出hello就结束了因为第二次调用next方法时遍历器状态已经变成终止了。但是如果使用throw方法抛出错误,不会影响遍历器状态。
上面代码只输出hello就结束了因为第二次调用next方法时遍历器状态已经变成终止了。但是如果使用throw命令抛出错误,不会影响遍历器状态。
```javascript
var gen = function* gen(){
@ -529,7 +529,7 @@ for(let value of delegatingIterator) {
// "Ok, bye."
```
上面代码中delegatingIterator是代理者delegatedIterator是被代理者。由于`yield* delegatedIterator`语句得到的值是一个遍历器所以要用星号表示。运行结果就是使用一个遍历器遍历了多个Genertor函数有递归的效果。
上面代码中delegatingIterator是代理者delegatedIterator是被代理者。由于`yield* delegatedIterator`语句得到的值是一个遍历器所以要用星号表示。运行结果就是使用一个遍历器遍历了多个Generator函数有递归的效果。
yield*语句等同于在Generator函数内部部署一个for...of循环。

View File

@ -95,7 +95,7 @@ interface IterationResult {
Iterator接口的目的就是为所有数据结构提供了一种统一的访问机制即for...of循环详见下文。当使用for...of循环遍历某种数据结构时该循环会自动去寻找Iterator接口。
ES6规定默认的Iterator接口部署在数据结构的`Symbol.iterator`属性,或者一个数据结构只要具有`Symbol.iterator`属性就可以认为是“可遍历的”iterable也就是说,调用`Symbol.iterator`方法,就会得到当前数据结构的默认遍历器。`Symbol.iterator`本身是一个表达式返回Symbol对象的iterator属性这是一个预定义好的、类型为Symbol的特殊值所以要放在方括号内请参考Symbol一)。
ES6规定默认的Iterator接口部署在数据结构的`Symbol.iterator`属性,或者说,一个数据结构只要具有`Symbol.iterator`属性就可以认为是“可遍历的”iterable。调用`Symbol.iterator`方法,就会得到当前数据结构的默认遍历器。`Symbol.iterator`本身是一个表达式返回Symbol对象的iterator属性这是一个预定义好的、类型为Symbol的特殊值所以要放在方括号内请参考Symbol一)。
在ES6中有三类数据结构原生具备Iterator接口数组、某些类似数组的对象、Set和Map结构。
@ -223,7 +223,7 @@ let obj = {
};
```
对于类似数组的对象存在数值键名和length属性部署Iterator接口有一个简便方法就是`Symbol.iterator`方法直接引用数的Iterator接口。
对于类似数组的对象存在数值键名和length属性部署Iterator接口有一个简便方法就是`Symbol.iterator`方法直接引用数的Iterator接口。
```javascript
NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
@ -265,10 +265,9 @@ while (!$result.done) {
**1解构赋值**
对数组和Set结构进行解构赋值时会默认调用iterator接口
对数组和Set结构进行解构赋值时会默认调用`Symbol.iterator`方法
```javascript
let set = new Set().add('a').add('b').add('c');
let [x,y] = set;
@ -276,7 +275,6 @@ let [x,y] = set;
let [first, ...rest] = set;
// first='a'; rest=['b','c'];
```
**2扩展运算符**
@ -337,7 +335,6 @@ iterator.next() // { value: undefined, done: true }
《数组的扩展》一章中提到ES6对数组提供entries()、keys()和values()三个方法,就是返回三个遍历器。
```javascript
var arr = [1, 5, 7];
var arrEntries = arr.entries();
@ -346,7 +343,6 @@ arrEntries.toString()
arrEntries === arrEntries[Symbol.iterator]()
// true
```
上面代码中entries方法返回的是一个遍历器iterator本质上就是调用了`Symbol.iterator`方法。
@ -354,7 +350,6 @@ arrEntries === arrEntries[Symbol.iterator]()
字符串是一个类似数组的对象也原生具有Iterator接口。
```javascript
var someString = "hi";
typeof someString[Symbol.iterator]
// "function"
@ -364,7 +359,6 @@ var iterator = someString[Symbol.iterator]();
iterator.next() // { value: "h", done: false }
iterator.next() // { value: "i", done: false }
iterator.next() // { value: undefined, done: true }
```
上面代码中,调用`Symbol.iterator`方法返回一个遍历器在这个遍历器上可以调用next方法实现对于字符串的遍历。

View File

@ -67,7 +67,7 @@ export function multiply (x, y) {
import {firstName, lastName, year} from './profile';
function sfirsetHeader(element) {
function setName(element) {
element.textContent = firstName + ' ' + lastName;
}
```
@ -124,7 +124,7 @@ export function circumference(radius) {
}
```
然后main.js文件输入circlek.js模块。
然后main.js文件输入circle.js模块。
```javascript
// main.js
@ -296,7 +296,7 @@ export { area as circleArea } from 'circle';
module math from "circleplus";
import exp from "circleplus";
console.log(exp(math.pi));
console.log(exp(math.PI));
```
上面代码中的"import exp"表示将circleplus模块的默认方法加载为exp方法。

View File

@ -260,7 +260,7 @@ someAsyncThing().then(function() {
});
```
上面代码中someAsyncThing函数产生的Promise对象会报错但是由于没有调用catch方法这个错误不会被捕获也不会传递到外层代码导致运行后没有任何输出。
上面代码中someAsyncThing函数产生的Promise对象会报错但是由于没有指定catch方法这个错误不会被捕获也不会传递到外层代码导致运行后没有任何输出。
```javascript
var promise = new Promise(function(resolve, reject) {
@ -272,7 +272,7 @@ promise.then(function(value) { console.log(value) });
// Uncaught Error: test
```
上面代码中Promise指定在下一轮“事件循环”再抛出错误结果由于没有指定catch语句就冒泡到最外层成了未捕获的错误。
上面代码中Promise指定在下一轮“事件循环”再抛出错误结果由于没有指定使用try...catch语句就冒泡到最外层成了未捕获的错误。因为此时Promise的函数体已经运行结束了所以这个错误是在Promise函数体外抛出的。
Node.js有一个unhandledRejection事件专门监听未捕获的reject错误。

View File

@ -38,7 +38,7 @@ ES6原生提供Proxy构造函数用来生成Proxy实例。
var proxy = new Proxy(target, handler)
```
Proxy对象的所用法都是上面这种形式不同的只是handler参数的写法。其中`new Proxy()`表示生成一个Proxy实例target参数表示所要拦截的目标对象handler参数也是一个对象用来定制拦截行为。
Proxy对象的所用法都是上面这种形式不同的只是handler参数的写法。其中`new Proxy()`表示生成一个Proxy实例target参数表示所要拦截的目标对象handler参数也是一个对象用来定制拦截行为。
下面是另一个拦截读取属性行为的例子。
@ -77,7 +77,7 @@ let obj = Object.create(proxy);
obj.time // 35
```
上面代码中proxy对象是obj对象的原型obj对象本身并没有time属性根据原型链会在proxy对象上读取该属性导致被拦截。
上面代码中proxy对象是obj对象的原型obj对象本身并没有time属性根据原型链会在proxy对象上读取该属性导致被拦截。
同一个拦截器函数,可以设置拦截多个操作。
@ -368,6 +368,7 @@ Reflect对象的方法清单如下。
- Reflect.defineProperty(target,name,desc)
- Reflect.getOwnPropertyNames(target)
- Reflect.getPrototypeOf(target)
- Reflect.setPrototypeOf(target, prototype)
- Reflect.deleteProperty(target,name)
- Reflect.enumerate(target)
- Reflect.freeze(target)

View File

@ -4,7 +4,7 @@
ES5的对象属性名都是字符串这容易造成属性名的冲突。比如你使用了一个他人提供的对象但又想为这个对象添加新的方法新方法的名字就有可能与现有方法产生冲突。如果有一种机制保证每个属性的名字都是独一无二的就好了这样就从根本上防止属性名的冲突。这就是ES6引入Symbol的原因。
ES6引入了一种新的原始数据类型Symbol表示独一无二的值。它是JavaScript语言的第八种数据类型前七种是数值、字符串、布尔值、数组、对象、函数、undefined
ES6引入了一种新的原始数据类型Symbol表示独一无二的值。它是JavaScript语言的第七种数据类型前六种是Undefined、Null、布尔值Boolean、字符串String、数值Number、对象Object
Symbol值通过Symbol函数生成。这就是说对象的属性名现在可以有两种类型一种是原来就有的字符串另一种就是新增的Symbol类型。凡是属性名属于Symbol类型就都是独一无二的可以保证不会与其他属性名产生冲突。