diff --git a/docs/class.md b/docs/class.md index 00ee674..3032c59 100644 --- a/docs/class.md +++ b/docs/class.md @@ -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__`属性,表示构造函数的继承,总是指向父类。 diff --git a/docs/generator.md b/docs/generator.md index 8a4150c..56cb8af 100644 --- a/docs/generator.md +++ b/docs/generator.md @@ -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循环。 diff --git a/docs/iterator.md b/docs/iterator.md index 7c4b349..97f2611 100644 --- a/docs/iterator.md +++ b/docs/iterator.md @@ -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方法,实现对于字符串的遍历。 diff --git a/docs/module.md b/docs/module.md index 6de58fe..2af3f9e 100644 --- a/docs/module.md +++ b/docs/module.md @@ -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方法。 diff --git a/docs/promise.md b/docs/promise.md index 7ef9541..4895158 100644 --- a/docs/promise.md +++ b/docs/promise.md @@ -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错误。 diff --git a/docs/proxy.md b/docs/proxy.md index 862932e..fe28f0c 100644 --- a/docs/proxy.md +++ b/docs/proxy.md @@ -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) diff --git a/docs/symbol.md b/docs/symbol.md index b45c5f8..a03826e 100644 --- a/docs/symbol.md +++ b/docs/symbol.md @@ -4,7 +4,7 @@ ES5的对象属性名都是字符串,这容易造成属性名的冲突。比如,你使用了一个他人提供的对象,但又想为这个对象添加新的方法,新方法的名字就有可能与现有方法产生冲突。如果有一种机制,保证每个属性的名字都是独一无二的就好了,这样就从根本上防止属性名的冲突。这就是ES6引入Symbol的原因。 -ES6引入了一种新的原始数据类型Symbol,表示独一无二的值。它是JavaScript语言的第八种数据类型,前七种是:数值、字符串、布尔值、数组、对象、函数、undefined。 +ES6引入了一种新的原始数据类型Symbol,表示独一无二的值。它是JavaScript语言的第七种数据类型,前六种是:Undefined、Null、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)。 Symbol值通过Symbol函数生成。这就是说,对象的属性名现在可以有两种类型,一种是原来就有的字符串,另一种就是新增的Symbol类型。凡是属性名属于Symbol类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。