ECMAScript 6 特性ECMAScript 6 特性

ECMAScript 6 特性

介绍

ECMAScript 6,也被称做ECMAScript 2015,是ECMAScript标准的下一个版本。这个标准预计将于2015年6月被正式批准。ES6是这门语言的一次重大更新,自ES5以来,该语言的首次更新是在2009年。主流Javascript引擎对ES6相关特性的实现也正在进行中

前往ES6标准草案查看ECMAScript 6的所有细节

ECMAScript 6 特性

Arrows

箭头函数

箭头函数是使用 => 语法简写的函数。在语法上类似C#、Java 8和CoffeeScript中对应的特性。他们同时支持表达式和语句块。和普通函数不同的是,箭头函数和上下文代码共享同一个词法this

// Expression bodies 表达式
var odds = evens.map(v => v + 1);
var nums = evens.map((v, i) => v + i);
var pairs = evens.map(v => ({even: v, odd: v + 1}));

// Statement bodies 语句块
nums.forEach(v => {
  if (v % 5 === 0)
    fives.push(v);
});

// Lexical this
var bob = {
  _name: "Bob",
  _friends: [],
  printFriends() {
    this._friends.forEach(f =>
      console.log(this._name + " knows " + f));
  }
}

Classes

ES6中提供了一个基于原型的面向对象模式的语法糖。简单的声明方式使得类模式变得更容易使用,增加了类的互用性。类支持原型继承、父方法调用、实例方法、静态方法和构造函数。

class SkinnedMesh extends THREE.Mesh {
  constructor(geometry, materials) {
    super(geometry, materials);

    this.idMatrix = SkinnedMesh.defaultMatrix();
    this.bones = [];
    this.boneMatrices = [];
    //...
  }
  update(camera) {
    //...
    super.update();
  }
  get boneCount() {
    return this.bones.length;
  }
  set matrixType(matrixType) {
    this.idMatrix = SkinnedMesh[matrixType]();
  }
  static defaultMatrix() {
    return new THREE.Matrix4();
  }
}

Enhanced Object Literals

增强的对象字面量

对象字面量扩展了以下特性,支持在构造时设置原型,foo: foo赋值的简写,方法定义,调用父方法,使用表达式计算属性名。同时这些也使得对象字面量和类声明更接近,基于对象的设计也在这种便利中受益。

var obj = {
    // __proto__
    __proto__: theProtoObj,
    // Shorthand for ‘handler: handler’
    handler,
    // Methods
    toString() {
     // Super calls
     return "d " + super.toString();
    },
    // Computed (dynamic) property names
    [ 'prop_' + (() => 42)() ]: 42
};

Template Strings

模板字符串

模板字符串提供了构建字符串的语法糖。这类似于Perl、Python和其他语言中的字符串插值特性。此外,作为可选项,使用标签可以自定义字符串的构建行为,避免注入攻击,或者基于字符串构建高阶的数据结构。

// 基本的字面量字符串创建
`In JavaScript '\n' is a line-feed.`

// 多行文本
`In JavaScript this is
 not legal.`

// 字符串插值
var name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?`

//构造一个HTTP请求,其中的GET前缀(译者注:即上文提到的标签)用来处理替换和构造逻辑
GET`http://foo.org/bar?a=${a}&b=${b}
    Content-Type: application/json
    X-Credentials: ${credentials}
    { "foo": ${foo},
      "bar": ${bar}}`(myOnReadyStateChangeHandler);

Destructuring

解构

解构允许使用模式匹配的绑定,支持数组和对象。解构是Fail-soft的,类似于对象的查找过程foo["bar"],未找到则会对应undefined

// 数组匹配
var [a, , b] = [1,2,3];

// 对象匹配
var { op: a, lhs: { op: b }, rhs: c }
       = getASTNode()

// 对象匹配的简写
// 绑定`op`,`lhs`,`rhs`到作用域中
var {op, lhs, rhs} = getASTNode()

// 也能被用在形参中
function g({name: x}) {
  console.log(x);
}
g({name: 5})

// Fail-soft的解构
var [a] = [];
a === undefined;

// 带默认值的Fail-soft解构
var [a = 1] = [];
a === 1;

Default + Rest + Spread

默认参数 + 剩余参数 + 参数展开

支持被调用函数设置参数的默认值。在调用函数时使用...可以将一个数组展开后作为参数传入。在定义函数时使用...可以将传入的剩余参数转化成一个数组。剩余参数取代了arguments的使用,它能以更直接的方式处理大多数问题。

function f(x, y=12) {
  // y is 12 if not passed (or passed as undefined)
  return x + y;
}
f(3) == 15
function f(x, ...y) {
  // y is an Array
  return x * y.length;
}
f(3, "hello", true) == 6
function f(x, y, z) {
  return x + y + z;
}
// Pass each elem of array as argument
f(...[1,2,3]) == 6

Let + Const

let和const关键字

let和const都是块级作用域的声明方式。let是新的varconst是单次赋值的。const的静态限制禁止变量在赋值前使用。

function f() {
  {
    let x;
    {
      // okay, block scoped name
      const x = "sneaky";
      // error, const
      x = "foo";
    }
    // error, already declared in block
    let x = "inner";
  }
}

Iterators + For..Of

迭代器和For..Of

Iterator对象让javascript拥有了像CLR IEnumerable和Java Iterable一样自定义迭代器的能力。将for..in转换成基于迭代器的自定义遍历的for..of形式。不需要实现一个类似LINQ中惰性设计模式的数组。

let fibonacci = {
  [Symbol.iterator]() {
    let pre = 0, cur = 1;
    return {
      next() {
        [pre, cur] = [cur, pre + cur];
        return { done: false, value: cur }
      }
    }
  }
}

for (var n of fibonacci) {
  // truncate the sequence at 1000
  if (n > 1000)
    break;
  console.log(n);
}

Iteration基于鸭子类型的接口(以下使用TypeScript的语法,仅供解释用)

interface IteratorResult {
  done: boolean;
  value: any;
}
interface Iterator {
  next(): IteratorResult;
}
interface Iterable {
  [Symbol.iterator](): Iterator
}

Generators

生成器

生成器使用yield或者function*()来定义,使用*声明的函数返回一个生成器实例,生成器是迭代器的子类,它提供了格外的方法nextthrow

var fibonacci = {
  [Symbol.iterator]: function*() {
    var pre = 0, cur = 1;
    for (;;) {
      var temp = pre;
      pre = cur;
      cur += temp;
      yield cur;
    }
  }
}

for (var n of fibonacci) {
  // truncate the sequence at 1000
  if (n > 1000)
    break;
  console.log(n);
}

Unicode

全面支持unicode:

// same as ES5.1
"?".length == 2

// new RegExp behaviour, opt-in ‘u’
"?".match(/./u)[0].length == 2

// new form
"\u{20BB7}"=="?"=="\uD842\uDFB7"

// new String ops
"?".codePointAt(0) == 0x20BB7

// for-of iterates code points
for(var c of "?") {
  console.log(c);
}

Modules

模块

ES支持从语言层面上使用模块进行组件定义。写法来自流行的Javascript模块加载器(AMD,CommonJS)。运行时的行为由宿主的加载器定义。内部使用了隐式的异步模型 - 在依赖的模块不可用或没处理前,当前模块的代码不会执行

// lib/math.js
export function sum(x, y) {
  return x + y;
}
export var pi = 3.141593;
// app.js
import * as math from "lib/math";
alert("2π = " + math.sum(math.pi, math.pi));
// otherApp.js
import {sum, pi} from "lib/math";
alert("2π = " + sum(pi, pi));

增加了export defaultexport *这些额外特性

// lib/mathplusplus.js
export * from "lib/math";
export var e = 2.71828182846;
export default function(x) {
    return Math.log(x);
}
// app.js
import ln, {pi, e} from "lib/mathplusplus";
alert("2π = " + ln(e)*pi*2);

Module Loaders

模块加载器

模块加载器支持:

  • 动态加载
  • 状态隔离
  • 全局命名空间隔离
  • 编译钩子
  • 嵌套虚拟化

默认的加载器可配置,也能构造新的加载器在隔离和约束的上下文中进行代码的执行和加载。

// 动态加载 – ‘System’是默认加载器
System.import('lib/math').then(function(m) {
  alert("2π = " + m.sum(m.pi, m.pi));
});

// 创建执行的沙盒 – 新的加载器
var loader = new Loader({
  global: fixup(window) // replace ‘console.log’
});
loader.eval("console.log('hello world!');");

// 直接操作模块的缓存
System.get('jquery');
System.set('jquery', Module({$: $})); // 警告:尚未完成

Map + Set + WeakMap + WeakSet

TODO

Proxies

TODO

Symbols

TODO

Subclassable Built-ins

TODO

Math + Number + String + Array + Object APIs

很多新库的加入,包括Math核心库,数组转化助手,字符串助手,还有用来拷贝的Object.assign

Number.EPSILON
Number.isInteger(Infinity) // false
Number.isNaN("NaN") // false

Math.acosh(3) // 1.762747174039086
Math.hypot(3, 4) // 5
Math.imul(Math.pow(2, 32) - 1, Math.pow(2, 32) - 2) // 2

"abcde".includes("cd") // true
"abc".repeat(3) // "abcabcabc"

Array.from(document.querySelectorAll('*')) // Returns a real Array
Array.of(1, 2, 3) // Similar to new Array(...), but without special one-arg behavior
[0, 0, 0].fill(7, 1) // [0,7,7]
[1, 2, 3].find(x => x == 3) // 3
[1, 2, 3].findIndex(x => x == 2) // 1
[1, 2, 3, 4, 5].copyWithin(3, 0) // [1, 2, 3, 1, 2]
["a", "b", "c"].entries() // iterator [0, "a"], [1,"b"], [2,"c"]
["a", "b", "c"].keys() // iterator 0, 1, 2
["a", "b", "c"].values() // iterator "a", "b", "c"

Object.assign(Point, { origin: new Point(0,0) })

Binary and Octal Literals

给binary (b)和octal (o)增加了两种新的数字字面量形式

0b111110111 === 503 // true
0o767 === 503 // true

Promises

Promise是用于异步编程的库。Promise作为将来可能获取到的值的容器。它已经被使用于很多现有的类库当中。

function timeout(duration = 0) {
    return new Promise((resolve, reject) => {
        setTimeout(resolve, duration);
    })
}

var p = timeout(1000).then(() => {
    return timeout(2000);
}).then(() => {
    throw new Error("hmm");
}).catch(err => {
    return Promise.all([timeout(100), timeout(200)]);
})

Reflect API

反射

整个反射接口暴露了对象在运行时级别的元操作。这其实和Proxy刚好相反,它允许在proxy捕获时调用与Proxy接口相对应的元操作。在实现proxies时尤其有用。

// No sample yet

Tail Calls

尾调用

保证尾调用不会导致栈空间无限制的增长。使得在没有限制输入的时候递归算法也能保证安全。

function factorial(n, acc = 1) {
    'use strict';
    if (n <= 1) return acc;
    return factorial(n - 1, n * acc);
}

// 在目前大多数实现中会导致栈溢出,
// 但在es6中没有限制的输入也是安全的
factorial(100000)

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Laoqi's Linux运维专列

正则三剑客-sed

与grep不同的是,当使用sed匹配字符串的时候如下: #sed -n ‘//‘p file             // 内填写需要匹配的字符串 例如: #s...

3055
来自专栏xingoo, 一个梦想做发明家的程序员

Log4j官方文档翻译(七、日志格式化)

apache log4j提供各种layout对象,然后根据自己指定的layouts对象转化日志信息。通常来说都是应用量身定制layout对象转换信息格式。 所有...

1975
来自专栏程序员八阿哥

Python从入门到摔门(5):18式优雅你的Python

在cmd中输入jupyter notebook --generate-config,然后找到生成的配置文件jupyter_notebook_config.py,...

992
来自专栏Nian糕的私人厨房

JavaScript 常见面试题分析(二)

④ call() 方法 apply() 方法 bind() 方法 (this 指向第一个参数)

943
来自专栏郭少华

ES6

在cmd命令窗口初始化项目-y代表全部默认同意,就不用一次次按回车了。命令执行完成后,会在项目根目录下生产package.json文件。

1633
来自专栏Golang语言社区

转--Golang语言-- Web 编程

1.golang的安装工具 1.1 GVM 第三方开发的Go多版本管理工具 2.golang环境变量 2.1 GOROOT=D:\go (golang 安装目录...

3636
来自专栏Golang语言社区

转--Golang语言-- Web 编程

1.golang的安装工具 1.1 GVM 第三方开发的Go多版本管理工具 2.golang环境变量 2.1 GOROOT=D:\go (golang 安装目录...

3718
来自专栏Golang语言社区

转-Go语言开发常见陷阱,你遇到过几个?

Go作为一种简便灵巧的语言,深受开发者的喜爱。但对于初学者来说,要想轻松驾驭它,还得做好细节学习工作。 初学者应该注意的地方: 大括号不能独立成行。 未使用变量...

3539
来自专栏大内老A

ASP.NET Web API中的Controller

虽然通过Visual Studio向导在ASP.NET Web API项目中创建的 Controller类型默认派生与抽象类型ApiController,但是A...

19410
来自专栏杨龙飞前端

js中的this关键字,setTimeout(),setInterval()的执行过程

1355

扫码关注云+社区

领取腾讯云代金券