ES6 系列 (一)
数组的扩展
Array.form () 将两类对象转换为数组
1. 类似数组的对象
2. 可遍历的对象
1 | let arrayLike = { |
ES5 写法
1 | var arr1 = [].slice.call(arrayLike) |
ES6 写法
1 | let arr2 = Array.form(arrayLike) |
任何有 length 属性的对象,都可以通过 Array.from 方法转为数组,而此时扩展运算符就无法转换。
值得提醒的是,扩展运算符(…)也可以将某些数据结构转为数组。
1 | // arguments对象 |
fill 方法使用给定值,填充一个数组。
1 | ['a', 'b', 'c'].fill(7) |
ES6 提供三个新的方法 ——entries()**,keys() 和 values ()**—— 用于遍历数组
1 | [1, 2, 3].includes(2); // true |
for of 循环
ES6 引入 rest 参数(形式为 “… 变量名”),用于获取函数的多余参数
扩展运算符(spread)是三个点(…)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。
console.log(…[1, 2, 3])
// 1 2 3
函数的 name 属性,返回该函数的函数名。
1 | function foo() {} |
(1)函数体内的 this 对象,就是定义时所在的对象,而不是使用时所在的对象。
对象的扩展
var bax= {bac} = var baz = {bac:bac}
1 | var o = { |
let propKey = ‘foo’;
let obj = {
[propKey]: true,
[‘a’ + ‘bc’]: 123
};
const person = {
sayName() {
console.log(‘hello!’);
},
};
person.sayName.name // “sayName”
Object.is()用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致。
1 | Object.is('foo', 'foo') |
Object.is(+0, -0) // false
Object.is(NaN, NaN) // true
Object.assign () 实行的是浅拷贝不是深拷贝
如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用。
例子
1 | var obj1 = {a: {b: 1}}; |
克隆对象
只能可通他自身的值而不能可通它继承的值
1 | function clone(origin){ |
1 | function clone(origin) { |
1 | Object.getOwnPropertyDescriptor 获取该属性的描述对象 |
Object.keys 方法,返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键名。
1 | var obj = { foo: 'bar', baz: 42 }; |
1 | var obj = { foo: 'bar', baz: 42 }; |
1 | var obj = { foo: 'bar', baz: 42 }; |
ES6 中遍历对象的属性
for…in 循环遍历对象自身的和继承的可枚举属性(不含 Symbol 属性)
Object.keys 返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含 Symbol 属性)。
Object.getOwnPropertyNames 返回一个数组,包含对象自身的所有属性(不含 Symbol 属性,但是包括不可枚举属性)
Object.getOwnPropertySymbols 返回一个数组,包含对象自身的所有 Symbol 属性。
__proto__属性(前后各两个下划线),用来读取或设置当前对象的 prototype 对象。目前,所有浏览器(包括 IE11)都部署了这个属性。
1 | // es6的写法 |
1 | let proto = {}; |
ES6 引入的原始类型 “
Symbol
凡是属性名属于 Symbol 类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。
Symbol 函数前不能使用 new 命令,否则会报错。这是因为生成的 Symbol 是一个原始类型的值,不是对象
由于 Symbol 值不是对象,所以不能添加属性。基本上,它是一种类似于字符串的数据类型。
Symbol 值不能与其他类型的值进行运算,会报错。
但是,Symbol 值可以显式转为字符串。
另外,Symbol 值也可以转为布尔值,但是不能转为数值。
let s = Symbol();
typeof s
数组去重
新增的数据结构 Set Map
1 | const s = new Set(); |
1 | var set = new Set([1, 2, 3, 4, 4]); |
// 去除数组的重复成员
在 Set 内部,两个 NaN 是相等。
1 | [...new Set(array)] |
1 | let map = new Map([ |
1 | for (let key of map.keys()) { |
Proxy(代理器) 元编程(对编程语言进行编程)
在目标对象之前设置一层拦截 外界对它的访问必须先通过这一层拦截
1 | var obj = new Proxy({}, { |
重写了 get 和 set 方法
1 | var proxy = new Proxy(target, handler); |
Promise (承诺)
所谓 Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。
1 | var promise = new Promise(function(resolve,reject){ |
遍历器对象本质上,就是一个指针对象。
回调函数
事件监听
发布 / 订阅
Promise 对象
Generator 函数
yield 表示执行到此处执行权将交给其它协程也就是说 yield 命令部两个阶段的分界线
Generator 函数不同于普通函数的另一个地方,即执行它不会返回结果,返回的是指针对象
1 | function* gen(x){ |
1 | var fetch = require('node-fetch'); |
Thunk 函数是自动执行 generator 函数的一种方法
传名调用
1 | f(x + 5) |
传值调用
1 | f(x + 5) |
Thunk 是传名调用的实现,将参数放到一个临时的函数中,再将这个临时函数传入函数体
这个临时函数叫做 Thunk 函数
1 | var x = 1; |
async :Generator 函数的语法糖
1 | var asyncReadFile = async function () { |
async 🌧️generator 比较
- async 有内置执行器 不需要调用 next 方法
拥有更好的语义(比起星号和 yield 语义更清楚了) - async 函数返回的是 promise 对象比 Generator 函数返回值是 Iterator 对象方便多了 可以用 then 方法指定下一步操作
async 和 await
- async 表示函数中有异步操作
- await 表示紧跟在后面的表达式需要等待结果
- async 函数完全可以看作多个异步操作,包装成的一个 Promise 对象,而 await 命令就是内部 then 命令的语法糖。
- async 函数返回一个 Promise 对象,可以使用 then 方法添加回调函数。当函数执行的时候,一旦遇到 await 就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。
错误处理
1 | async function f() { |
class
基本形式
1 | class Point{ |
Class 不存在变量提升(hoist),这一点与 ES5 完全不同。
1 | const MyClass = class Me { |
类名是 MyClass 而不是 me Me 只在 Class 的内部代码可用,指代当前类。
const MyClass = class { /* … */ };
模块加载方案
CommonJs 应用于服务器
AMD 应用于浏览器
ES6 提供模块功能 尽量的静态化)
1 | import {stat,exut,readFile} from 'fs' |
Es6 模块是编译时加载
ES6 的模块自动采用严格模式
1 | function f(){} |
1 | import {lastName as surname} from './profile' |
1 | 导出 |
使用 import 命令的时候用户不需要知道所加载的变量名或者函数名 用这个语法可以为模块指定默认输出
1 | export default function (){ |
引入的时候 import 可以为该匿名函数指定任意的名字,这个时候 import 的后面不使用大括号
1 | import customName from .. |
foo 的函数名 foo 在模块外部时无效的 视同匿名函数加载
使用 export 时,对应的 import 语句需要使用大括号。
使用 export default 对应的 import 语句不需要大括号
1 | // 第一组 |
本质上,export default 就是输出一个叫做 default 的变量或方法,然后系统允许你为它取任意名字。所以,下面的写法是有效的。
import { default as xxx } from ‘modules’
1 | export {add as default}; |
// 等同于
1 | // export default add; |
ES6 模块
1 | <script type="module" src="foo.js"></script> |
都是异步加载,不会造成堵塞浏览器,即等到整个页面渲染完,再执行模块脚本,等同于打开了