http://es6.ruanyifeng.com/#docs/intro
这里有个es的笔记可以看看:http://www.cnblogs.com/yang-11/p/6053556.html
0001关于 Object.assign()痛点 http://blog.csdn.net/waiterwaiter/article/details/50267787 这个只是一个1级的拷贝,使用的时候需要注意点。
写一些,自己认为应该记住的es6的东西。不常用的就不说了。
1.let,const参见阮一峰老师的。记住有let,const,class,import这6种生命的方法。import用来代替require.
2.解构赋值赋值,我们可以了解数组,对象,字符串的赋值就行。
3.数组的扩展。
Array.from()用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括ES6新增的数据结构Set和Map
Array.from
还可以接受第二个参数,作用类似于数组的map
方法,用来对每个元素进行处理,将处理后的值放入返回的数组。
第二个参数的实用的例子:
Array.of
方法用于将一组值,转换为数组
Array
方法没有参数、一个参数、三个参数时,返回结果都不一样。只有当参数个数不少于2个时,Array()
才会返回由参数组成的新数组。参数个数只有一个时,实际上是指定数组的长度。
数组实例的find
方法,用于找出第一个符合条件的数组成员。它的参数是一个回调函数,所有数组成员依次执行该回调函数,直到找出第一个返回值为true
的成员,然后返回该成员。如果没有符合条件的成员,则返回undefined
。
而findIndex返回的是坐标 。
fill
方法使用给定值,填充一个数组。
['a', 'b', 'c'].fill(7)
// [7, 7, 7]
new Array(3).fill(7)
// [7, 7, 7]
['a', 'b', 'c'].fill(7, 1, 2) // ['a', 7, 'c']
上面代码表示,fill
方法从1号位开始,向原数组填充7,到2号位之前结束。
ES6提供三个新的方法——entries()
,keys()
和values()
——用于遍历数组。它们都返回一个遍历器对象(详见《Iterator》一章),可以用for...of
循环进行遍历,唯一的区别是keys()
是对键名的遍历、values()
是对键值的遍历,entries()
是对键值对的遍历。
如果不使用for...of
循环,可以手动调用遍历器对象的next
方法,进行遍历。
let letter = ['a', 'b', 'c']; let entries = letter.entries(); console.log(entries.next().value); // [0, 'a'] console.log(entries.next().value); // [1, 'b'] console.log(entries.next().value); // [2, 'c']
includes
该方法的第二个参数表示搜索的起始位置,默认为0。如果第二个参数为负数,则表示倒数的位置,如果这时它大于数组长度(比如第二个参数为-4,但数组长度为3),则会重置为从0开始。
indexOf
方法有两个缺点,一是不够语义化,它的含义是找到参数值的第一个出现位置,所以要去比较是否不等于-1,表达起来不够直观。二是,它内部使用严格相当运算符(===)进行判断,这会导致对NaN
的误判。
[NaN].indexOf(NaN)
// -1
includes
使用的是不一样的判断算法,就没有这个问题。
[NaN].includes(NaN)
// true
[1, 2, 3].includes(2); // true
[1, 2, 3].includes(4); // false
[1, 2, NaN].includes(NaN); // true
备注;
Map和Set数据结构有一个has
方法,需要注意与includes
区分。
- Map结构的
has
方法,是用来查找键名的,比如Map.prototype.has(key)
、WeakMap.prototype.has(key)
、Reflect.has(target, propertyKey)
。 - Set结构的
has
方法,是用来查找值的,比如Set.prototype.has(value)
、WeakSet.prototype.has(value)
数组的空位指,数组的某一个位置没有任何值。比如,Array
构造函数返回的数组都是空位。
我们要避免空位。
4.函数的扩展。
(1) 默认值。
(2)函数的.length属性。参数的个数,如果参数有默认值则不算,或者有默认值的参数放在第一个的话,length也是0.
(3)rest函数。
(4) 扩展运算符(spread)是三个点(...
)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。
应用代替apply:
1)合并数组
扩展运算符提供了数组合并的新写法。
(2)与解构赋值结合
扩展运算符可以与解构赋值结合起来,用于生成数组。
(3)函数的返回值
JavaScript的函数只能返回一个值,如果需要返回多个值,只能返回数组或对象。扩展运算符提供了解决这个问题的一种变通方法。
(4)字符串
扩展运算符还可以将字符串转为真正的数组
(5)实现了Iterator接口的对象
任何Iterator接口的对象,都可以用扩展运算符转为真正的数组。
(6)Map和Set结构,Generator函数
扩展运算符内部调用的是数据结构的Iterator接口,因此只要具有Iterator接口的对象,都可以使用扩展运算符,比如Map结构。
5.name
属性
6.箭头函数。
ES6允许使用“箭头”(=>
)定义函数。
7.set
ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。
上面代码通过add
方法向 Set 结构加入成员,结果表明 Set 结构不会添加重复的值。
Set 函数可以接受一个数组(或类似数组的对象)作为参数,用来初始化。
上面代码中,也展示了一种去除数组重复成员的方法。
// 去除数组的重复成员 [...new Set(array)]
let set = new Set();
set.add({});
set.size // 1
set.add({});
set.size // 2
上面代码表示,由于两个空对象不相等,所以它们被视为两个值
add(value)
:添加某个值,返回Set结构本身。delete(value)
:删除某个值,返回一个布尔值,表示删除是否成功。has(value)
:返回一个布尔值,表示该值是否为Set
的成员。clear()
:清除所有成员,没有返回值。
s.add(1).add(2).add(2); // 注意2被加入了两次 s.size // 2 s.has(1) // true s.has(2) // true s.has(3) // false s.delete(2); s.has(2) // false
keys()
,values()
,entries()
Set结构的实例默认可遍历,它的默认遍历器生成函数就是它的values
方法。
forEach()
let set = new Set([1, 2, 3]);
set.forEach((value, key) => console.log(value * 2) )
// 2
// 4
// 6
8.map
map的size属性,set(key, value),get(key),has(key),delete(key),clear()
keys()
:返回键名的遍历器。values()
:返回键值的遍历器。entries()
:返回所有成员的遍历器。forEach()
:遍历Map的所有成员
上面代码最后的那个例子,表示Map结构的默认遍历器接口(Symbol.iterator
属性),就是entries
方法。
9.Class
这个是以为b.__proto__ == B.prototype
如果构造器有return并且返回的不是this的话,那么需要小心了。
私有方法。
this的指向。
Class的继承
类的prototype属性和__proto__属性
大多数浏览器的ES5实现之中,每一个对象都有__proto__
属性,指向对应的构造函数的prototype属性。Class作为构造函数的语法糖,同时有prototype属性和__proto__
属性,因此同时存在两条继承链。
原生构造函数的继承。
以前,这些原生构造函数是无法继承的,比如,不能自己定义一个Array
的子类
中间超出的那一行:
this.splice(0, this.length, ...this.history[this.history.length - 1]);
Class的取值函数(getter)和存值函数(setter)
Class的静态属性和实例属性
Class内部只有静态方法,没有静态属性。
这么写是有效的。
除此之外,还有一种写法,虽然es6不支持,但是babel已经支持了。
10.Symbol
ymbol 作为属性名,该属性不会出现在for...in
、for...of
循环中,也不会被Object.keys()
、Object.getOwnPropertyNames()
、JSON.stringify()
返回。但是,它也不是私有属性,有一个Object.getOwnPropertySymbols
方法,可以获取指定对象的所有 Symbol 属性名。
Object.getOwnPropertySymbols
方法返回一个数组,成员是当前对象的所有用作属性名的 Symbol 值。
Symbol.for(),Symbol.keyFor()
有时,我们希望重新使用同一个Symbol值,Symbol.for
方法可以做到这一点。它接受一个字符串作为参数,然后搜索有没有以该参数作为名称的Symbol值。如果有,就返回这个Symbol值,否则就新建并返回一个以该字符串为名称的Symbol值。
单利模式:
Symbol.hasInstance
对象的Symbol.isConcatSpreadable
属性等于一个布尔值,表示该对象使用Array.prototype.concat()
时,是否可以展开。
对象的Symbol.species
属性,指向当前对象的构造函数。创造实例时,默认会调用这个方法,即使用这个属性返回的函数当作构造函数,来创造新的实例对象
对象的Symbol.match
属性,指向一个函数。当执行str.match(myObject)
时,如果该属性存在,会调用它,返回该方法的返回值。
对象的Symbol.replace
属性,指向一个方法,当该对象被String.prototype.replace
方法调用时,会返回该方法的返回值。
对象的Symbol.search
属性,指向一个方法,当该对象被String.prototype.search
方法调用时,会返回该方法的返回值。
对象的Symbol.split
属性,指向一个方法,当该对象被String.prototype.split
方法调用时,会返回该方法的返回值。
11.关于es6的class
http://blog.csdn.net/pcaxb/article/details/53759637
12.三个点拓展符的多个用法。
https://www.cnblogs.com/mingjiezhang/p/5903026.html
下面的coolcao的笔记。以后再精简吧。
## es6分享
### es6新的内容可简单归纳为几个部分:
* 新的语法定义
* let,const
* class,extend
* 模板字符串
* 不定参数和默认参数
* 解构
* 箭头函数
* 新的数据结构及类型
* Set,Map
* Symbols
* 迭代器,生成器,Promise
* 代理 Proxy 和 Reflect
* 模块系统 Modules
* 对es5已有的对象的拓展
* 字符串的拓展
* 正则的拓展
* 数值的拓展
* 数组的拓展
* 对象的拓展
* 函数的拓展
### 推荐重点研究的新特性
* Promise
* Iterator 和 for of循环
* Generator函数
* class和extend 对继承的拓展
* 箭头函数
### 稍微看一下文档,平时练习用即可,难度不大
* let,const
* 模板字符串
* 不定参数和默认参数
* 解构(nodejs 6.0后才开始支持解构)
* Symbols(平时用的不多)
* 代理Proxy 和 反射 Reflect
* 模块系统 (nodejs一直用的自己的模块系统,和es6的模块系统差别不大,只是语法上有点区别)
* 各种拓展
### Promise
promise三种状态:初始等待状态pending,完成状态resolved,拒绝状态rejected
#### 异常捕捉
异步的js回调,没法使用try catch去捕捉异常,只能约定在回调函数的第一个参数传err,第二个参数传结果
但是使用promise可以将异常统一catch
promise链的最后都要用catch去捕捉异常,这样链条上任何promise出了错误或是被拒绝都会被catch到。
```javascript
MongoClient.connect('mongodb://localhost:27017',function(err,db){
var collection = db.collection('simple_query');
collection.find({},function (err,result) {
console.log(result);
});
});
```
改写成promise形式:
```js
MongoClient.connect('mongodb://localhost:27017').then(function (db) {
return db.collection('simple_query');
}).then(function (coll) {
return coll.find();
}).then(function (result) {
console.log(result);
}).catch();
```
promise形成一个链,在处理流程时逻辑更清晰。
整个promise的概念,很容易理解。无非就是如下的示意图流程:
```javascript
------fulfilled(resolved)-----then(value)方法调用
|
pending ----
|
------rejected---------catch(error)方法调用
```
但是在实际使用的时候,如果对其概念理解不深,会跳入很多坑,分享一下自己遇到的一些。
#### 遇到的坑,值得注意的问题
##### then()方法的参数,永远传递函数
then()方法有两个参数,onSuccess()处理成功时的函数,onFail()处理失败时的函数,但是一般如果在最后的链添加了catch方法,则只需要传一个处理成功的函数即可。
* 但如果传两个参数,而且最后还添加了catch会如何?
```javascript
var p = new Promise(function (resolved,rejected) {
setTimeout(function () {
let a = false;
if(a){
resolved(true);
}else{
rejected(false);
}
},1000);
});
p.then(function onSuccess(result) {
console.log(result);
},function onFail(err) {
console.log('onFail');
console.log(err);
}).catch(function (err) {
console.log('catch err');
console.log(err);
});
```
结果:
```
onFail
false
```
#### then()方法的返回
前面一直提promise链,也没说Promise是怎么成链的,其实是通过then()方法的返回promise形成的一个链。
```javascript
var r = p.then(function onSuccess(result) {
console.log(result);
},function onFail(err) {
console.log('onFail');
console.log(err);
}).catch(function (err) {
console.log('catch err');
console.log(err);
});
console.log(r); //Promise { <pending> }
```
then()方法返回的是一个Promise,处于初始状态,在then()方法的成功函数中,return 的值会相应的改变r的状态。
处理函数return 有三种类型:
* return 一个Promise
* return 一个同步的值
* throw 一个异常
前两种方法都会相应的将promise的状态改为resolved.throw一个异常会改变其状态为rejected.
然后就可以使用r.then().catch()进行相应的处理。
这样的代码会比较凌乱,一般都是如下面这样链式的写法,形成promise链:
```javascript
p.then(function onSuccess(result) {
console.log(result);
return 'abc';
},function onFail(err) {
console.log('onFail');
console.log(err);
}).then(function (result) {
console.log(result); //abc
return 'def';
}).then(function (result) {
console.log(result); //def
}).catch(function (err) {
console.log('catch err');
console.log(err);
});
```
#### promise的金字塔问题
```javascript
remotedb.allDocs({
include_docs: true,
attachments: true
}).then(function (result) {
var docs = result.rows;
docs.forEach(function(element) {
localdb.put(element.doc).then(function(response) {
alert("Pulled doc with id " + element.doc._id + " and added to local db.");
}).catch(function (err) {
if (err.status == 409) {
localdb.get(element.doc._id).then(function (resp) {
localdb.remove(resp._id, resp._rev).then(function (resp) {
// et cetera...
```
这样的代码,只是用了promise的写法,并没有使用promise的链式写法,原因是没有正确上面then()方法的返回值。这样,导致逻辑混乱,结构不清晰,还不如直接用回调来的清晰。
```javascript
remotedb.allDocs(...).then(function (resultOfAllDocs) {
return localdb.put(...);
}).then(function (resultOfPut) {
return localdb.get(...);
}).then(function (resultOfGet) {
return localdb.put(...);
}).catch(function (err) {
console.log(err);
});
```
#### promise中使用循环
例如有这样一个简单的场景,从数据库中查询出所有状态为0的商品,然后将所有的商品删除。
```javascript
coll.find({status:0}).then(function (docs) {
docs.forEach(function (doc) {
return doc.remove();
});
}).then(function () {
console.log('全部删除');
});
```
这样写是不对的,因为,假设有100个状态为0的文档,在使用forEach循环时,如果第一个文档删除成功了,return 回去后,整个promise的状态就改变了,那么即使后面的99个删除失败,也不会再抛出错误,导致操作失败。
正确的应该是,使用promise.all()。
```javascript
coll.find({status:0}).then(function (docs) {
return Promise.all(docs.forEach(doc){
return doc.remove();
});
})
```
将100个文档遍历,返回100个删除操作的promise,然后Promise.all()传递一个100个promise的数组。最后当这100个promse都成功时,才算最终的成功。
#### catch()和then(,...)并非完全等价
上面说过,异常的处理,可以用catch也可以在then传第二个参数异常处理函数处理,但这并不完全等价。
```javascript
somePromise().then(function () {
return someOtherPromise();
}).catch(function (err) {
// handle error
});
somePromise().then(function () {
return someOtherPromise();
}, function (err) {
// handle error
});
```
比如上面的代码,如果在someOtherPromise()这个函数里报错了,第一个是可以正常catch到的,因为在promise链里的任何异常都可以被catch捕捉到。
但是第二个,却没法捕捉到,因为then()方法第二个参数只能处理调用then()方法的promise的异常,这里是somePromise()的异常。
**在promise链的最后一定要加catch()**
### Iterator 和 for of
Iterator遍历器,类似java的遍历器
遍历器不断调用next()方式遍历所有数据
next方法必须返回一个包含value和done两个属性的对象。value属性是当前遍历的位置的值,而done属性是一个布尔值,用来表示遍历是否结束。
遍历器是一种数据遍历机制,任何对象,只要实现了这种机制,都可以使用同种方式,也就是for of进行遍历。
Iterator的遍历过程是这样的。
(1)创建一个指针对象,指向当前数据结构的起始位置。也就是说,遍历器对象本质上,就是一个指针对象。
(2)第一次调用指针对象的next方法,可以将指针指向数据结构的第一个成员。
(3)第二次调用指针对象的next方法,指针就指向数据结构的第二个成员。
(4)不断调用指针对象的next方法,直到它指向数据结构的结束位置。
js中默认实现了遍历器接口的有数组,Set,Map,字符串等,也可以自行实现,然后使用for of 循环遍历。
ES6规定,默认的Iterator接口部署在数据结构的Symbol.iterator属性,或者说,一个数据结构只要具有Symbol.iterator属性,就可以认为是“可遍历的”(iterable)。调用Symbol.iterator方法,就会得到当前数据结构默认的遍历器生成函数。Symbol.iterator本身是一个表达式,返回Symbol对象的iterator属性,这是一个预定义好的、类型为Symbol的特殊值,所以要放在方括号内(请参考Symbol一章)。
```javascript
let arr = ['a', 'b', 'c'];
let iter = arr[Symbol.iterator]();
iter.next() // { value: 'a', done: false }
iter.next() // { value: 'b', done: false }
iter.next() // { value: 'c', done: false }
iter.next() // { value: undefined, done: true }
```
自行实现iterable接口:
```javascript
class RangeIterator {
constructor(start, stop) {
this.value = start;
this.stop = stop;
}
[Symbol.iterator]() { return this; }
next() {
var value = this.value;
if (value < this.stop) {
this.value++;
return {done: false, value: value};
} else {
return {done: true, value: undefined};
}
}
}
function range(start, stop) {
return new RangeIterator(start, stop);
}
for (var value of range(0, 3)) {
console.log(value);
}
```
### Generator函数,yield
生成器函数内部实现了遍历器接口iterable,使用next()方法调用值。
```javascript
function* helloWorldGenerator() {
yield 'hello';
yield 'world';
return 'ending';
}
var hw = helloWorldGenerator(); //生成一个遍历器对象
hw.next(); //{ value: 'hello', done: false }
hw.next(); //{ value: 'world', done: false }
hw.next(); //{ value: 'ending', done: true }
hw.next(); //{ value: undefined, done: true }
```
由于Generator函数返回的遍历器对象,只有调用next方法才会遍历下一个内部状态,所以其实提供了一种可以暂停执行的函数。yield语句就是暂停标志。
遍历器对象的next方法的运行逻辑如下。
(1)遇到yield语句,就暂停执行后面的操作,并将紧跟在yield后面的那个表达式的值,作为返回的对象的value属性值。
(2)下一次调用next方法时,再继续往下执行,直到遇到下一个yield语句。
(3)如果没有再遇到新的yield语句,就一直运行到函数结束,直到return语句为止,并将return语句后面的表达式的值,作为返回的对象的value属性值。
(4)如果该函数没有return语句,则返回的对象的value属性值为undefined。
#### 生成器函数有什么用
TJ大神将Promise,Generator的思想揉在一起,写了一个co模块,异步流程控制模块。
```javascript
co(function *(){
// resolve multiple promises in parallel
var a = Promise.resolve(1);
var b = Promise.resolve(2);
var c = Promise.resolve(3);
var res = yield [a, b, c];
console.log(res);
// => [1, 2, 3]
}).catch(onerror);
```
co模块实质是一个生成器执行器,不用我们自己调用next()方法,也不用我们自己调用promise的then()方法。co模块给执行的。
原理就是,当生成器函数遇到yield时,会停下当前执行状态,返回一个promise,这时候可以调用promise的then()方法获取值。
所以不论同步异步,在代码感官上都一样,都好像是“同步”的。
目前(es7还未出来之前),生成器函数+co模块+promise方式控制异步流程的方式被大家所推崇。出了莫名其妙的加了一层co之外,这种方式也没什么不好。
但是有一个前提是,co模块yield后面必须跟的是promise,不能是其他的值。
所以promise还是万物的基础。
#### 解决异步流程方式比较
##### 单纯的promise
可以使用promise链的方式,这种方式逻辑简单明了,但是如果开发人员对promise理解不深,很容易出bug
##### co+生成器函数
比较受大家推崇的一种方式,但是需要额外引入co模块,还需要理解生成器函数,写出的代码很容易不受控制。但是在代码层面,可以用同步的代码解决异步流程
##### es7的async和await
```javascript
var asyncReadFile = async function (){
var f1 = await readFile('/etc/fstab');
var f2 = await readFile('/etc/shells');
console.log(f1.toString());
console.log(f2.toString());
};
```
async函数就是将Generator函数的星号(*)替换成async,将yield替换成await
* 内置执行器
* 更好的语义
* 更广的适用性 使用co,yield后面只能跟promise或thunk函数,但是await后面可以跟proise或是基本类型的值
* 返回值是Promise Generator返回的是一个遍历器,而async返回的是promise
可以说,es7的async和await才是解决异步流程问题的终极大招
### class和extend的实现
js的继承使用的是原型链的方式,代码写起来太复杂,凌乱。es6引入了class关键字去定义一个构造函数,extend关键字实现继承
但其本质上,继承关系还是通过原型链的方式实现的。
```javascript
//定义类
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return '(' + this.x + ', ' + this.y + ')';
}
static print(){
console.log('(' + this.x + ', ' + this.y + ')');
}
}
let point = new Point(3,4);
```
class和extend简化了js中对象的继承,在逻辑上也更清晰明了。但也不是非常完美的,目前es6里class里可以定义静态方法,但是不能定义静态属性,如果想要在某个class上定义一个静态属性,那么只能通过原始的方式进行了,例如:
```javascript
Point.sql = {
insert:'insert into points (x,y) values (?,?)'
}
```
### 箭头函数
借鉴的coffeescript的箭头函数,当然并不只是形式上的简便,在实现上也有改进:
(1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
```javascript
var obj = {
name: 'coolcao',
say: function() {
return {
name: 'world',
say: function() {
console.log(this.name);
}
}
}
};
var obj2 = {
name: 'coolcao',
say: function() {
return {
name: 'world',
say: () => {
console.log(this.name);
}
}
}
};
obj.say().say();
obj2.say().say();
```
(2)不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
(3)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用Rest参数代替。
(4)不可以使用yield命令,因此箭头函数不能用作Generator函数。
```javascript
let sayHi = (name) = > {
console.log('hi ' + name);
}
```
ES6 *
* let,const
* class,extend
*
*
*
*
* * Set,Map
* Symbols
* Promise
* Proxy Reflect * Modules
*
* Promise
* Iterator for of
* Generator
* class extend
*
var queryByPage = function (page,limit) {
page = page || 1;
limit = limit || 5;
console.log({page:page,limit:limit});
}
es6
var queryByPage = function (page = 1,limit = 5) { console.log({page:page,limit:limit});
}
js arguments es6 arguments
function containsAll(array) {
for (var i = 1; i < arguments.length; i++) {
var item = arguments[i];
if (haystack.indexOf(item) === -1) {
return false; }
}
return true; }
var containsAll = function containsAll(array,...items) { for (let item of items) {
if(array.indexOf(item) === -1){ return false;
} }
return true; }
1. arguments array , arguments
1
2.
Iterator for of Iterator
ES6 Iterator 1
2 3 4
var it = makeIterator(['a', 'b']);
it.next() // { value: "a", done: false } it.next() // { value: "b", done: false }
it.next() // { value: undefined, done: true }
function makeIterator(array) {
var nextIndex = 0;
return {
next: function() {
return nextIndex < array.length ?
{value: array[nextIndex++], done: false} :
{value: undefined, done: true};
}
};
}
next next
next
ES6 Iterator
let arr = ['a', 'b', 'c'];
for-of
es6 set,map,
for...of
Symbol.iterator
let iter = arr[Symbol.iterator]();
iter.next() // { value: 'a', done: false } iter.next() // { value: 'b', done: false } iter.next() // { value: 'c', done: false }
iter.next() // { value: undefined, done: true }
let obj = {
data: [ 'hello', 'world' ],
[Symbol.iterator]() {
const self = this;
let index = 0;
return {
next() {
if (index < self.data.length) {
return {
value: self.data[index++],
done: false
};
}
} else {
}
return { value: undefined, done: true };
};
}
};
function* helloWorldGenerator() { yield 'hello';
yield 'world';
return 'ending';
}
var hw = helloWorldGenerator();
hw.next()
// { value: 'hello', done: false }
hw.next()
// { value: 'world', done: false }
hw.next()
// { value: 'ending', done: true }
hw.next()
// { value: undefined, done: true }
Generator Generator Generator
co co
var loadUser = function () {
return new Promise(function (resolve,reject) {
setTimeout(function () { resolve('coolcao');
},1000); });
}
var findBooksByUser = function (user) {
return new Promise(function (resolve,reject) { setTimeout(function () {
resolve('js '); },1000);
}); }
co(function *() {
var user = yield loadUser();
console.log(user);
var book = yield findBooksByUser(user);
console.log(book);
});
class
class User { constructor(name,age) {
this.name = name;
this.age = age; }
toString(){
return `User[name:${this.name},age:${this.age}]`;
} valueOf(){
return this.age; }
// User.sayHi()
static sayHi(){ console.log(‘hi’);
} }
var u = new User(‘coolcao’,23);
class class prototype js Java
class 1.
var u = new User(); class User{}
2.class new 3.class
User.sql = {}
class extends
class Men extends User { constructor(name,age) {
super(name,age);
this.gender = 'm'; }
}
var m = new Men('coolcao',23);
console.log(m);
console.log(m instanceof User);
//true class
coffeescript
1 this
2 new
3 arguments Rest
4 yield Generator
```javascript var obj = {
name: 'coolcao', say: function() {
return {
name: 'world',
say: function() {
console.log(this.name); }
} }
};
var obj2 = {
name: 'coolcao',
say: function() {
return {
name: 'world',
say: () => {
console.log(this.name); }
} }
};
obj.say().say(); obj2.say().say(); ```
Promise promise pending, resolved, rejected
js try catch err, promise catch promise catch promise catch
```javascript MongoClient.connect('mongodb://localhost:27017',function(err,db){
var collection = db.collection('simple_query'); collection.find({},function (err,result) {
console.log(result); });
}); ```
promise : ```js
MongoClient.connect('mongodb://localhost:27017').then(function (db) { return db.collection(‘simple_query');
return Promise.resolve(db.collection(‘simple_query');); }).then(function (coll) {
return coll.find(); }).then(function (result) {
console.log(result); }).catch();
```
------fulfilled(resolved)-----then(value)
| pending --- |
———rejected---------catch(error)
箭头函数有几个使用注意点。
(1)函数体内的this
对象,就是定义时所在的对象,而不是使用时所在的对象。
(2)不可以当作构造函数,也就是说,不可以使用new
命令,否则会抛出一个错误。
(3)不可以使用arguments
对象,该对象在函数体内不存在。如果要用,可以用Rest参数代替。
(4)不可以使用yield
命令,因此箭头函数不能用作Generator函数。
上面四点中,第一点尤其值得注意。this
对象的指向是可变的,但是在箭头函数中,它是固定的。