ES6学习总结

2017.11.12

数值的扩展

二进制和八进制表示法,分别使用0b和0o表示

Number.isFinite()和Number.isNaN()
与传统的isFinite和isNaN方法的区别在于,传统方法先调用Number()将非数值的值转换为数值,再进行判断,而这个新的方法只对数值有效,非数值一律返回false

Number,isInteger()
用来判断一个值是否为整数。但是需要注意的是,在JavaScript中,整数和浮点数都同样是同样的存储方法,所以3和3.0都被视为同一个值

数组的扩展

Array.from()
用于将两类对象转换为真正的数组
一类是类数组对象(array-like-object)和可遍历的(iterable)的对象,其中包括ES6新增的Set和Map结构。

Array.from的一个应用是将字符串转换为数组,然后返回字符串的长度

Array.of()方法
将用于一组值,转换为数组

Array.of(3, 11, 8) // [3,11,8]
Array.of(3).length // 1

这样做的目的在于弥补构造函数Array()的不足。因为参数的个数的不同,会导致Array行为差异

Array() // []
Array(3) // [undefined, undefined, undefined]
Array(3,11,8) // [3, 11, 8]

数组实例的find()方法
用于找出第一个符合条件的数组元素,它的参数是一个回调函数,回调函数的参数——当前值,当前位置和原数组

findIndex()和find方法类似

fill()
使用给定值,填充一个数组

还可以接受第二个和第三个参数
用于指定填充的起始位置和结束位置

['a', 'b', 'c'].fill(7, 1, 2)
// ['a', 7, 'c']

数组实例的entries(),keys(),values()
它们都返回一个遍历器,可以使用for ... of循环进行遍历,唯一的区别是keys()是对键名的遍历、values()是对键值的遍历,entries()是对键值对的遍历。

数组推导
数组推导可以代替map方法和filter方法
需要注意的是数组推导的方括号构成了一个单独的作用域,在这个方括号中声明的变量类似于let语句声明的变量
还有一个注意点就是,新数组会立即在内存中生效,这时。如果原数组是一个很大的数组的话,将会非常的耗费内存

Array.observe()和Array.unobserve()
这两个方法用于监听(取消监听)数组的变化,指定回调函数
属于ES7中的内容

对象的扩展

ES6中允许字面量定义对象时候,用表达式作为对象的属性名,即把表达式放到方括号内

Object.is()
用来判断两个值是否严格相等。它与严格相等符(===)的行为基本一致,不同之处在于:-0不等于+0,NaN等于自身

Object.assign()
用来将源对象(Sourse)的所有可枚举属性,复制到目标对象。它至少需要两个对象作为参数,第一个是目标对象,后面都是源对象

assign()用法很多
为对象添加属性
为对象添加方法
克隆对象
为属性指定默认值

proto属性
用来读取或设置当前对象的prototype对象
Object.setPrototypeOf()
用来设置一个对象的prototype对象
Object.getPrototypeOf()
用于读取一个对象的prototype对象


函数的扩展

ES6允许为函数设置默认值,即直接写在参数定义的后面

需要注意的一点是,参数默认值所处的作用域是函数作用域,而不是全局作用域

reset参数(...变量名)
用来获取函数的多余参数,这样就不用使用arguments对象了。reset参数搭配的变量是一个数组,该变量将多余的参数放进一个数组中

扩展运算符(spread)
是三个点(...),它好比reset参数的逆运算,将一个数组用逗号分隔的参数序列。该运算符主要用于函数调用

扩展运算符内部调用的是数据结构的iterator接口,因此只要具有iterator接口的对象,都可以使用扩展运算符,比如map结构

箭头函数
如果箭头函数中不需要参数或者需要多个参数,就使用一个圆括号代表参数部分
如果代码部分多于一条代码,就要使用大括号将它们括起来,并且使用return语句返回

另外由于大括号被解析成代码块,所以如果箭头函数返回一个对象的话,必须在对象外面加上括号

var getTempItem = id => ({ id: id, name: "Temp" });

箭头函数的作用
简化回调函数

需要注意点
1.函数体内的this对象,绑定的是定义时候的所在的对象,而不是使用时候所在的对象
2.不可以当做构造函数
3.不可以使用arguments对象,该对象在函数体内不存在

this的指向是可变的,但在箭头函数中,它是固定的。


ES6学习总结_第1张图片
image.png

set和map数据结构

Set
set方法提供了一种数组去重的方式

function dedupe(array){
    return Array.from(new Set(array));
}

类似于数组,但是成员是唯一的,没有重复的值

遍历操作
set结构有一个values方法,返回一个遍历器
set结构的默认遍历器就是它的values方法,也就是说,可以忽略values方法,直接使用for ... of循环遍历set

set结构的forEach方法

也有keys和entries方法,这个时候每个值的键名就是键值

由于扩展运算符(...)内部使用for...of循环,所以也可以用于set结构

let set = new Set(['red', 'green', 'blue']);
let arr = [...set]; 
// ['red', 'green', 'blue']

提供了一种便捷的数组去重的方式

let arr = [3, 5, 2, 2, 5, 5];
let unique = [...new Set(arr)]; 
// [3, 5, 2]

map
基本用法
提出原因:因为JavaScript对象,本质上是键值对的集合,但是只能用字符串当做键。(这里所受的限制就很大了)

作为构造函数
Map可以接受一个数组作为参数,该数组的成员是一个表示键值对的数组

map的键实际上是跟内存地址绑定的,只要内存地址不一样,就视为两个键。

map结构转化为数组结构,比较快速的方法是使用扩展运算符(...)

map还有一个forEach方法,与数组的forEach方法类似,也可以实现遍历
还可以接受第二个参数,用来绑定this

WeakMap只接受对象作为键名(null除外),不接受原始数据的值作为键名,而且键名所指向的对象,不计入垃圾回收机制

iterator

遍历器是一种接口规格,任何对象只要部署这个接口,就可以完成遍历操作
作用:
1.为各种数据结构,提供一个统一的、 简便的接口
2、使得对象中的各个属性能够按着某种次序排列

遍历器提供了一个指针,指向当前对象的某个属性,使用next方法,就可以将指针移动到下一个属性。next方法返回一个包含value和done两个属性的对象。其中value属性是当前遍历位置的值,done属性是一个布尔值,表示遍历是否结束

在Es6中,有三类数据结构原生具备Iterator接口:数组、类数组对象、Set和map结构

ES6中,一个对象只要部署了@@iterator方法,就被视为具有iterator接口,就可以使用for...of循环遍历它的值。也就是说,for....of循环内部调用是原对象的symbol.iterator方法

JavaScript原有的for...in循环,只能获取对象的键名,不能直接获取键值。ES6提供的for...of循环,允许遍历获取键值

var arr = ["a", "b", "c", "d"];
for (a in arr) {
  console.log(a); // 0 1 2 3
}

for (a of arr) {
  console.log(a); // a b c d
}

总结一下,for...of循环可以使用的范围包括数组、类似数组的对象(比如arguments对象、DOM NodeList对象)、Set和Map结构、后文的Generator对象,以及字符串。

Generator

可以把它理解成一个函数内部状态的遍历器,每调用一次,函数内部的状态发生一次改变(可以理解成发生某些事件)。为了可以完全控制函数内部的状态的改变,依次遍历这些状态

两个特征
1、function命令和函数名之前有一个*号
2、函数内部使用yield语句

当调用Generator函数的时候,该函数并不执行,而是返回一个遍历器(可以理解为暂停执行)
使用next方法遍历yield语句定义的内部状态

总结一下,Generator函数使用iterator接口,每次调用next方法的返回值,就是一个标准的iterator返回值:有着value和done两个属性的对象。其中,value是yield语句后面那个表达式的值,done是一个布尔值,表示是否遍历结束。

return和yield语句的区别

区别在于每次遇到yield,函数暂停执行,下一次再从该位置继续向后执行,而return语句不具备位置记忆的功能

Generator函数可以不用yield语句,这时候就变成了一个单纯的暂缓执行函数

next()方法的参数
next方法可以带一个参数,该参数就会被当做上一个yield语句的返回值

for....of循环可以遍历Generator函数,而且此时不再需要调用next方法

yield*语句
如果yield命令后面跟的是一个遍历器,需要在yield命令后面加上星号,表明它返回的是一个遍历器

yield*命令可以很方便地取出嵌套数组中所有的成员

作为对象属性的Generator函数

let obj = {
  \* myGeneratorMethod() {
    ···
  }
};

还可以写成:

let obj = {
  myGeneratorMethod: function* () {
    ···
  }
};

这两者是等价的

应用:
Generator可以暂停函数的执行,返回任意表达式的值

1、异步操作的同步化表达
2、控制流管理
注意,yield语句是同步运行,而不是异步运行
3、部署iterator接口
4、作为数据结构

Class和Module

Class
ES5通过构造函数,定义并生成新的对象。

function Point(x,y){
    this.x = x;
    this.y = y;
}

Point.prototype.toString = function () {
    return '('+this.x+', '+this.y+')';
}

ES6引入了Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类

//定义类
class Point {

  constructor(x, y) {
    this.x = x;
    this.y = y;
  }

  toString() {
    return '('+this.x+', '+this.y+')';
  }

}

var point = new Point(2,3);
point.toString() // (2, 3)

注意:里面有一个constructor函数,这就是构造函数,而this关键字则代表实例对象。定义方法的时候,不需要加上function这个保留字,直接把函数定义放进去就可以了

Class之间可以通过extends关键字实现继承

class ColorPoint extends Point {}

super关键字,它指向父类的同名方法。

注意:类和模块的内部,默认就是严格模式,所以不需要使用use strict指定的运行模式

Module的基本模块
ES6模块的设计思想,是尽量的静态化,使得编译时候就能够确定模块的依赖关系,以及输入和输出的变量

模块功能主要由两个命令构成:export和import
export命令用于用户自定义的模块,规定对外接口;import命令用于输入其他模块提供的功能,同时创建命名空间(namescape),防止函数名冲突

ES6允许将独立的JS文件作为模块,也就是说,允许一个JavaScript脚本文件调用另一个脚本文件

如果想为输入的变量重新取一个名字,import语句中使用as关键字,将输入的的变量重命名

module命令可以取代import语句,达到整体输入模块的作用

module circle from 'circle'

export default
如果需要输出匿名函数,可以使用export default命令
import进来的时候,可以为该匿名函数指定任意名称

模块的继承

promise对象

所谓的promise对象,就是代表了未来某个将要发生的事件(通常是一个异步操作)。
用处:有了promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数

ES6中的promise对象是一个构造函数,用来生成Promise实例,下面是promise对象的基本用法

var promise = new Promise(function(resolve, reject) {
  if (/* 异步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});

promise.then(function(value) {
  // success
}, function(value) {
  // failure
});

promise实例生成后,可以使用then方法分别指定resolve方法和reject方法的回调函数

function timeout(ms) {
  return new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
}

timeout(100).then(() => {
  console.log('done');
});

上面代码的timeout方法返回一个Promise实例对象,表示一段时间以后改变自身状态,从而触发then方法绑定的回调函数。

resolve和reject方法调用的时候,都有参数。它们的参数会被传递给回调函数。reject方法的参数通常是Error对象的实例,而resolve方法的参数除了正常的值以外,还可能是另一个Promise实例

Promise.prototype.then:链式操作
Promise.prototype.then返回的是一个新的promise对象

getJSON("/posts.json").then(function(json) {
  return json.post;
}).then(function(post) {
  // proceed
});

第一个回调函数完成之后,会将返回结果作为参数,传入第二个回调函数

如果前一个回调函数返回的是promise对象,这时后一个回调函数就会等待该promise对象有了运算结果,才进行下一步的调用

这种设计使得嵌套的异步操作,可以被很容易的改写,从回调函数的“横向发展”变成“向下发展”

promise.prototype.catch方法:捕捉错误
该方法是Promise.prototype.then(null,rejection)的别名,用于指定发生错误时候的回调函数

Promise.all方法 Promise.race方法
这两个方法用于将多个promise实例,包装成一个新的Promise实例

Promise.resolve方法 Promise.reject方法
有时候需要将现有的对象转化为Promise对象
如果Promise.resolve方法的参数,不是具有then方法的对象(又称thenable对象),则返回一个新的promise对象,而且它的状态为fullfilled

var p = Promise.resolve('Hello');

p.then(function (s){
  console.log(s)
});
// Hello

Promise.resolve方法的参数就是回调函数的参数

Promise.reject(reason)方法也会返回一个新的Promise实例,该实例的状态为rejected。Promise.reject方法的参数reason,会被传递给实例的回调函数。

var p = Promise.reject('出错了');

p.then(null, function (s){
  console.log(s)
});
// 出错了

async函数
async函数是用来取代回调函数的另一种方法

只要函数名前面加上async关键字,就表明该函数内部有异步操作。该异步操作应该返回一个Promise对象,前面用await关键字注明。当函数执行的时候,遇到await就会先返回,等到触发的异步操作完成,再接着执行函数体内后面的语句

async function getStockPrice(symbol, currency) {
    let price = await getStockPrice(symbol);
    return convert(price, currency);
}


function timeout(ms) {
  return new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
}

async function asyncValue(value) {
  await timeout(50);
  return value;
}

你可能感兴趣的:(ES6学习总结)