Osheep

时光不回头,当下最重要。

ES2015的基本语法

我们在开发的过程中,或多或少的接触了ES2015的语法,有时候我们遇到点问题,可以在网上去查找相应的API,查看其使用方法和原理。但是,这样的途径虽然有用,效率不高,花了些时间,把ES2015的一些新特性添加进去,并作了一些简单的记录,以供后用。

  1. ES5中Array对象中引入Array.forEach 方法来代替 for循环,其中Array.forEach 方法的特定是自带闭包,以解决因为缺乏块级作用域导致需要使用取巧的方法来解决var的作用域的问题。

for...of...循环中的每一个值保存在所对应的循环体中,解决了Array.forEach的回调书写

  1. 箭头函数(Arrow Function),属于匿名函数,不推荐使用其作为定义式函数使用。

  2. 模板字符串,使用反勾号(backtick,` )

  3. 对象字面量扩展语法,为开发者扩展了更多的对象(Object)的操作权限。

  • 函数属性省略写法
//before
foo: function() {
  //...
},

// after
bar() { 
  //...
}
  • 支持 __proto__ 注入
import { EventEmitter } from 'events'
const machine = {
    __proto__: new EventEmitter(),
    method() {
        // ...
    }
}
  • 可动态计算属性名
const prefix = 'es2015: '
const obj = {
  [prefix+'enhancedObject']: 'foobar'
}
  • 将属性名定义省略
const foo = 123
const bar = () => foo
const obj = {
  foo,
  bar
}
  • 表达式结构:多返回值的特性
    解构别名:“:x”, x就是它的别名
    在Promise找那个,要传递多余一个返回值得时候,我们可以使用解构特性实现
function fetchData() {
    return new Promise((resolve, reject) => {
        resolve(['foo','bar'])
    })
}

fetchData()
.then(([value1, value2]) => {
    // 带有解构参数的箭头函数的时候,解构参数必须要有一个括号包裹
    console.log(value1, value2) // foo ,bar
 })

使用ES2015的 for-of循环,配合const , Array.entries() 等特性,可以写出被控制语句终止的语句出来。

const arr = ['mike','Peter','Ben','William','John']
for (const { index, item } of arr.entries()) {
    console.log(index, item)
    if( item.match(/\^W/) ) break 
}
  1. 函数参数表达、传参
  • 默认参数值
    Syntax: function name(arg = defaultValue) { ... }
  • 剩余参数
    ES6引入了 Array.from可以将一个类数组转变成一个数组对象
  • arguments与剩余参数
    arguments会跟随上下文绑定都上层,所以在不确定上下文绑定结果的情况下,尽可能不要在箭头函数中使用arguments,而是使用 …args
  • 解构传参
    apply和call可以让开发者自定义一个上下文。可以改变函数的上下文,还能以程序化的方式控制函数的传入参数。但是有时候,函数内部没有对上下文做任何访问的,所有apply和call的意义只在于控制传入参数,而上下文则可能会使用 null 代替。
function sum(...numbers) {
    return numbers.reduce((a,b) => a + b)
}
// 这时使用null替换为上下文
sum.apply(null, [1, 2, 3])

ES2015中的解构传参同样使用数组作为传入参数控制函数调用情况,不同的是解构传参不会替换函数调用中的上下文
同样使用 … 作为语法糖提示符
Syntax: fn(...[arg1, arg2])

function sum(...numbers) {
  return numbers.reduce((a,b) => a + b)
}
sum(...[1,2,3])  // => 6
  1. 新的数据结构
    值类型的数据结构:

    • String – 字符串
    • Number – 数值
    • Boolean – 布尔型
    • Null – 空值
    • Undefined – 为定义值

引用类型数据结构:

  • Object – 对象
  • Array – 数组
  • RegExp – 正则表达式
  • Date – 日期
  • Error – 错误

6.1 Set有序集合

数组和集合的区别:

数组 集合
元素序列 有序 无序
元素可重复性 语速可重复 元素不可重复
  • 使用语法 Syntax: new Set([itertable]) : Set
    cosnt set = new Set()
    集合对象操作方法:
操作方法(语法) 方法内容
set.add(value) 添加元素到集合内
set.delete(value) 删除集合内的制定元素
set.clear() 清空集合内的元素
set.forEach(callbackFn[, context]) 遍历集合内的所有元素,并作为第一参数调用callbackFn
set.has(value) 检查集合内是否含有某元素

集合对象自身定义了 forEach 方法,跟数组类型中的 forEach 一样,传入一个回调函数以接受集合内的元素,

const set = new Set([1,2,3,4])
set.forEach( item => {
    console.log( item  )
})

6.2 WeakSet
合理运用内存的方案。
WeakSet和Set的区别

  • WeakSet 不能包含值类型元素,否则则会抛出一个 TypeError
  • WeakSet 不能包含 无引用 的对象,否则会自动清除出集合
  • WeakSet 无法被探知其大小,也无法被探知其中所包含的元素

WeakSet存在的最大意义在于:可以让我们直接对引擎中垃圾收集器的运行情况有程序化的探知方式,开发者可以利用 WeakSet 的特性以更高的定制化方案来优化程序的内存使用方案。

操作方法(语法) 方法内容
map.set(key, value) 添加键值对到映射中
map.get(key) 获取映射中某一个键的对应值
map.delete(key) 将某一个键值对移除出映射
map.clear() 清空映射中的所有键值对
map.entries() 返回一个以二元数组(键值对)作为元素的数组
map.has(key) 检查映射中是否包含某一键值对
map.keys() 返回一个以当前映射中所有键值对作为元素的可迭代对象
map.values() 返回一个以当前映射中所有值作为元素的可迭代对象
map.size 映射中键值对的数量

6.3 Map映射类型
映射类型在计算机科学中的定义属于 关联数组(Associative Array),而关联数组的定义为若干个键值对组成的集合,其中每一个键(key)都只能出现一次。
使用语法: Syntax: new Mapp([iterable]) : Map
映射对象操作方法

操作方法(语法) 方法内容
map.set(key, value) 添加键值对到映射中
map.get(key) 获取映射中某一个键的对应值
map.delete(key) 将某一个键值对移除出映射
map.clear() 清空映射中的所有键值对
map.entries() 返回一个以二元数组(键值对)作为元素的数组
map.has(key) 检查映射中是否包含某一键值对
map.keys() 返回一个以当前映射中所有键值对作为元素的可迭代对象
map.values() 返回一个以当前映射中所有值作为元素的可迭代对象
map.size 映射中键值对的数量

映射对象与普通对象的区别

映射对象Map 普通对象 Object
存储键值对 ✔️ ✔️
遍历所有键值对 ✔️ ✔️
检查是否包含指定键值对 ✔️ ✔️
使用字符串(String)作为键 ✔️ ✔️
使用Symbol作为键 ✔️ ✔️
使用任意对象作为键 ✔️
可以方便地得知键值对的数量 ✔️

6.4 WeakMap
与集合对象(Set)一样,和其很类似。

  1. 类语法(Classes)
    7.1 基本定义语法
//Syntax: 
class name {
    constructor() {
        //... 原本的构造函数
    }

    fn() {
        // ... 原本定义在 prototype 中的方法
    }
 }

7.2 集成语法

// class SubClass extends SuperClass {}

如果子类集成了父类,必须在子类 constructor 中使用 super函数调用父类的构造函数后才能在子类的constructor 构造函数中使用 this,否则会报错: ReferenceError: this is not defined,其他方法this依然指向当前实例

7.3 Getter/Setter
元编程(Meta-programming),元编程的特定雨荨程序可以对运行时(runtime)的对象进行读取和操作,从而使程序可以脱离代码从字面上为程序定义的一些限制,有了对对象更高操作权限。

const Counter = {
  _count = 0,
  get value() {
    return ++this._count
  }
}

7.4 静态方法
在定义的类上面挂在方法属性,以满足一些特殊的需求,比如:Array.isArray() 这个isArray就是静态方法

  1. 生成器(Generator)
    生成器的主要功能是:通过一段程序,持续迭代或枚举出符合某个公式或算法的有序数列中的元素。

yield语句的作用与return语句有些相似,但并非推出函数体,而是切出当前函数的运行时(此处为一个类协程,Semi-coroutine),与此同时可以将一个值(可以是任何类型)带到主线程中。

从计算机科学角度看,生成器是一种类协程或半协程(Semi-coroutine),它提供了一种可以通过特定语句或方法使其执行对象(Execution)暂停的功能,而这语句一般都是 yield 语句。

  1. Promise
    其有三种状态:等待(Pending),成功(Fulfilled),失败(Rejected)
  • resolve(value)方法控制的是当前 Promise 对象是否进入成功状态,一旦执行该方法并传入有且至于一个的返回值,Promise便会从等待状态(Pending)进入成功状态(Fulfilled)
  • reject(reason)进入失败状态

return 语句并不会使 Promise 对象进入成功状态,而会使Promise停留在等待状态。所以在Promise对象的执行器(executor)内需要谨慎使用return语句控制流程

8.2 高级使用方法

  • Promise.all(iterable),传入一个可迭代对象,并返回一个Promise对象
1.如果迭代对象中的所有Promise都进入了成功状态,那么该方法返回的Promise对象也会进入成功状态,并以一个可迭代对象来承载其中的所有返回值。

2. 如果迭代对象有一个进入失败状态,返回的Promise对象也会进入到失败状态,并以那个失败状态的错误信息作为自己的错误信息。
  • Promise.race(iterable),同样接受迭代对象,其等待其中的第一个进入完成状态的Promise对象。一但有一个Promise对象进入了完成状态,这个Promise就会改变
  1. 代码模块化
    // 引入默认模块
    Syntax: import namespace from 'module-name'
    // 引入模块部分接口
    Syntax: import { member1, member2 } from 'module-name'
    // 模块引入重命名
    Syntax: import { member as alias } from 'module-name'
    // 引入全部局部接口到指定命名空间
    Syntax: import * as namespace from 'module-name'
    // 混入引入默认接口和命名接口
    Syntax: import { default as <default name>, method1 } from 'module-name'
    // 更简洁的引入默认接口和命名接口
    Syntax: import <default name>, { <name modules> } from 'module-name'
    // 不接入接口,仅运行模块代码
    Syntax: import 'module-name'
  • 定义模块
    // 暴露单一接口
    Syntax: export <statement>

    • 声明部分(Statement)为export语句提供了所暴露接口的标识
    • 赋值部分(Assignment)为export语句提供了接口的值

// 暴露模块默认接口
Syntax: export default <value>
// 混合使用暴露接口语句
可以同时使用export语句和export default语句

  • 从其他模块博暴露接口
    • 暴露一个模块的所有接口
      Syntax: eport * from 'other-module'
    • 暴露一个模块的部分接口
      Syntax: export { member } from 'module-name'
    • 暴露一个模块的默认接口
      Syntax: export { default } from 'module'
  1. Symbol
    Symbol是一种互不等价的标志。
    Symbol的实例值带有互不等价的特性,即任意两个Symbol值都不相等。ES2015中,字面量对象除了可以使用字符串,数字作为属性键外,还可以使用Symbol 作为属性键
    Symbol是一种值类型,而不是引用类型,这跟其他值类型(字符串,数字等)的行为是一致的
  1. Proxy
    可以对任何对象的绝大部分行为进行监听和干涉,实现更多的自定义程序行为
    Syntax: new Proxy(target, handler)
    监听器属性、参数及监听内容
属性键 监听器参数 监听内容
has (target, prop) 监听in语句的使用
get (target, prop, reciver) 监听目标对象的属性读取
set (target, prop, value, reciver) 监听目标对象赋值
deleteProperty (target, prop) 监听delete语句对目标对象的删除属性行为
ownKeys (target) 监听Object.getOwnPropertyNames()的读取
apply (target, thisArg, arguments) 监听目标函数(作为目标对象)的调用行为
construct (target, arguments, newTarget) 监听目标构造函数(作为目标对象)利用new 而生成实例的行为
getPrototypeOf (target) 监听Object.getPrototypeOf()的读取
setPrototypeOf (target, prototype) 监听Object.setPrototypeOf()的调用
isExtensible (target) 监听Object.isExtensible()的读取
preventExtensions (target) 监听preventExtensions()的读取
getOwnPropertyDescriptor (target, prop) 监听Object.getOwnPropertyDescriptor()的调用
defineProperty (target, property, descriptor) 监听Object.defineProperty()的调用
点赞

发表评论

电子邮件地址不会被公开。