专栏首页nummyECMAScript 6 特性ECMAScript 6 特性

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 条评论
登录 后参与评论

相关文章

  • Django生产环境下如何查看Debug信息

    我们知道,部署Django到生产环境时,settings.DEBUG必须设置为False, 否则会带来很大的安全隐患。

    用户2936342
  • R绘图时x轴刻度过长被裁减的解决办法

    解决办法 调用par()函数设置外边框的大小,默认外边框的大小为mar=c(5.1,4.1,4.1,2.1), 分别对应下,左,上,右四个外边框。

    用户2936342
  • pandas将含有多值的内容分拆成多行

    在同一列中,本该分别填入多行中的数据,被填在一行里了,然而在分析的时候,需要拆分成为多行。

    用户2936342
  • Javascript 笔记

    JavaScript表单验证电话号码,判断一个输入量是否为电话号码,通过正则表达式实现。 //检查电话号码 function isTel(str){      ...

    Hongten
  • [基础]电话/手机常见验证的Javascript示例

    电话号码:<input type="text" id="TelPrefix" size="4" MaxLength="4"> - <input type="te...

    菩提树下的杨过
  • 前端:JavaScript闭包

    渔父歌
  • js日期计算及快速获取周、月、季度起止日

    机缘巧合,这段接触了一下js,刚开始各种磕碰各种不顺手,一个日期计算都折腾我半天,积累了一些,赶紧码下:  

    AhDung
  • 总结Js方法工具类库,总有你需要的方法

    实际开发工程中,会遇到一些重复的逻辑功能处理或者说是比较繁琐的前端函数。粗略整理了一下,希望对正在浏览的你有所帮助,也希望帮助新入行的小白们解决一下工作中的负担...

    Parker
  • 名企刷题指南-剑指offer第5期(45-55题)

    45.LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张^_^)...他随机从中抽出了5张牌,想测测自己的手气,看...

    前端迷
  • 第112天:javascript中函数预解析和执行阶段

    关于javascript中的函数:    1、预解析:把所有的函数定义提前,所有的变量声明提前,变量的赋值不提前    2、执行 :从上到下执行,但有例外(se...

    半指温柔乐

扫码关注云+社区

领取腾讯云代金券