IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    ECMAScript 6新特性介绍

    dwqs发表于 2015-06-22 02:45:28
    love 0

    箭头函数

    箭头函数使用=>语法来简化函数,在语句结构上和C#、Java 8 和 CoffeeScript类似,支持表达式和函数体。。=>`操作符左边为输入的参数,而右边则是进行的操作以及返回的值。

    1. var sum = (num1, num2) => num1 + num2;
    2. // 等同于
    3. var sum = function(num1, num2) {
    4. return num1 + num2;
    5. };

    关于this,绑定定义时所在的对象,而不是使用时所在的对象。

    1. var handler = {
    2. id: "123456",
    3. init: function() {
    4. document.addEventListener("click",
    5. event => this.doSomething(event.type), false);
    6. },
    7. doSomething: function(type) {
    8. console.log("Handling " + type + " for " + this.id);
    9. }
    10. };

    上面代码的init和doSomething方法中,都使用了箭头函数,它们中的this都绑定handler对象。否则,doSomething方法内部的this对象就指向全局对象,运行时会报错。
    箭头函数有几个使用注意点。

    1.函数体内的this对象,绑定定义时所在的对象,而不是使用时所在的对象。
    2.不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
    3.不可以使用arguments对象,该对象在函数体内不存在。

    类

    ES6中的类是基于面相对象模式的简单语法糖,拥有一个方便的声明形式,让类模式更容易使用。类支持原型继承、父类调用、实例、静态方法和构造函数。

    1. class SkinnedMesh extends THREE.Mesh {
    2. constructor(geometry, materials) {
    3. super(geometry, materials);
    4. this.idMatrix = SkinnedMesh.defaultMatrix();
    5. this.bones = [];
    6. this.boneMatrices = [];
    7. //...
    8. }
    9. update(camera) {
    10. //...
    11. super.update();
    12. }
    13. get boneCount() {
    14. return this.bones.length;
    15. }
    16. set matrixType(matrixType) {
    17. this.idMatrix = SkinnedMesh[matrixType]();
    18. }
    19. static defaultMatrix() {
    20. return new THREE.Matrix4();
    21. }
    22. }

    增强的对象字面量

    对象字面量支持在结构中设置原型,简化了foo: foo赋值、方法定义(省略function)、父类调用操作并能结合表达式计算属性名,这些使对象字面量更符合类的概念,在编写面向对象的JavaScript时更加轻松方便了。

    1. var obj = {
    2. // __proto__
    3. __proto__: theProtoObj,
    4. // Shorthand for ‘handler: handler’
    5. handler,
    6. // Methods
    7. toString() {
    8. // Super calls
    9. return "d " + super.toString();
    10. },
    11. // Computed (dynamic) property names
    12. [ 'prop_' + (() => 42)() ]: 42
    13. };

    字符串模板

    字符串模板是构建字符串的语法糖,这类似于Perl和Python中的字符串插值。允许在字符串中添加一个自定义标签,避免注入攻击或用字符串内容构建更高层次的数据结构。

    模板字符串(template string)是增强版的字符串,即可以当作普通字符串使用,也可以在字符串中嵌入变量。它用反引号(`)标识。

    1. // Basic literal string creation
    2. `In JavaScript '\n' is a line-feed.`
    3. // Multiline strings
    4. `In JavaScript this is
    5. not legal.`
    6. // String interpolation
    7. var name = "Bob", time = "today";
    8. `Hello ${name}, how are you ${time}?`
    9. // Construct an HTTP request prefix is used to interpret the replacements and construction
    10. GET`http://foo.org/bar?a=${a}&b=${b}
    11. Content-Type: application/json
    12. X-Credentials: ${credentials}
    13. { "foo": ${foo},
    14. "bar": ${bar}}`(myOnReadyStateChangeHandler);

    解构

    解构允许数组和对象使用模式匹配进行绑定。解构是故障弱化的,类似于标准对象以foo['foo']方式查找变量,当没有找到时返回undefined。

    1. // list matching
    2. var [a, , b] = [1,2,3];
    3. // object matching
    4. var { op: a, lhs: { op: b }, rhs: c }
    5. = getASTNode()
    6. // object matching shorthand
    7. // binds `op`, `lhs` and `rhs` in scope
    8. var {op, lhs, rhs} = getASTNode()
    9. // Can be used in parameter position
    10. function g({name: x}) {
    11. console.log(x);
    12. }
    13. g({name: 5})
    14. // Fail-soft destructuring
    15. var [a] = [];
    16. a === undefined;
    17. // Fail-soft destructuring with defaults
    18. var [a = 1] = [];
    19. a === 1;

    参数默认值+不定参数+拓展参数

    现在可以在定义函数的时候指定参数的默认值了,而不用像以前那样通过逻辑或操作符来达到目的了。

    1. function sayHello(name){
    2. //传统的指定默认参数的方式
    3. var name=name||'dude';
    4. console.log('Hello '+name);
    5. }
    6. //运用ES6的默认参数
    7. function f(x, y=12) {
    8. // y is 12 if not passed (or passed as undefined)
    9. return x + y;
    10. }
    11. f(3) == 15
    12. sayHello();//输出:Hello dude
    13. sayHello('Wayou');//输出:Hello Wayou

    如果传递的实参个数超过函数定义的形参个数,则可用通过arguments对象来访问。ES6支持不定参数的概念,不定参数是在函数中使用命名参数同时接收不定数量的未命名参数,格式是三个句点后跟代表所有不定参数的变量名。

    1. function f(x, ...y) {
    2. // y is an Array
    3. return x * y.length;
    4. }
    5. f(3, "hello", true) == 6

    拓展参数则是另一种形式的语法糖,它允许传递数组或者类数组直接做为函数的参数而不用通过apply。

    1. function f(x, y, z) {
    2. return x + y + z;
    3. }
    4. // Pass each elem of array as argument
    5. f(...[1,2,3]) == 6

    let+const

    let用于定于块级作用域,const用于定义常量,其值不可改变。需要注意的是,let声明的变量不存在“变量提升”现象。

    1. function f() {
    2. {
    3. let x;
    4. {
    5. // okay, block scoped name
    6. const x = "sneaky";
    7. // error, const
    8. x = "foo";
    9. }
    10. // error, already declared in block
    11. let x = "inner";
    12. }
    13. }

    for…of 值遍历

    for...in在遍历时是遍历对象或数组的键,但是for...of则是遍历对象或数组的值。

    1. var someArray = [ "a", "b", "c" ];
    2. for (v of someArray) {
    3. console.log(v);//输出 a,b,c
    4. }
    5. for (r in someArray) {
    6. console.log(r);//输出 0,1,2
    7. }

    iterator+generator

    具体内容可以参考这里:iterator, generator

    • iterator:它是这么一个对象,拥有一个next方法,这个方法返回一个对象{done,value},这个对象包含两个属性,一个布尔类型的done和包含任意值的value
    • iterable: 这是这么一个对象,拥有一个obj[@@iterator]方法,这个方法返回一个iterator
    • generator: 它是一种特殊的iterator。反的next方法可以接收一个参数并且返回值取决与它的构造函数(generator function)。generator同时拥有一个throw方法
    • generator 函数: 即generator的构造函数。此函数内可以使用yield关键字。在yield出现的地方可以通过generator的next或throw方法向外界传递值。generator 函数是通过function*来声明的
    • yield 关键字:它可以暂停函数的执行,随后可以再进进入函数继续执行

    模块

    在ES6标准中,JavaScript原生支持module了,将不同功能的代码分别写在不同文件中,各模块只需导出公共接口部分,然后通过模块的导入的方式可以在其他地方使用。

    1. // lib/math.js
    2. export function sum(x, y) {
    3. return x + y;
    4. }
    5. export var pi = 3.141593;
    6. // app.js
    7. import * as math from "lib/math";
    8. alert("2π = " + math.sum(math.pi, math.pi));
    9. // otherApp.js
    10. import {sum, pi} from "lib/math";
    11. alert("2π = " + sum(pi, pi));

    支持export default 和 export *:

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

    模块加载器

    模块加载器支持:

    • 动态加载(Dynamic loading)
    • 状态一致性(State isolation)
    • 全局空间一致性(Global namespace isolation)
    • 编译钩子(Compilation hooks)
    • 嵌套虚拟化(Nested virtualization)

    默认的加载器是可以配置的,新的加载器能构建评估并在独立或受限的上下文中加载代码。

    1. // Dynamic loading – ‘System’ is default loader
    2. System.import('lib/math').then(function(m) {
    3. alert("2π = " + m.sum(m.pi, m.pi));
    4. });
    5. // Create execution sandboxes – new Loaders
    6. var loader = new Loader({
    7. global: fixup(window) // replace ‘console.log’
    8. });
    9. loader.eval("console.log('hello world!');");
    10. // Directly manipulate module cache
    11. System.get('jquery');
    12. System.set('jquery', Module({$: $})); // WARNING: not yet finalized

    Map + Set + WeakMap + WeakSet

    新加的集合类型,提供了更加方便的获取属性值的方法,同时,在进行属性值添加与获取时有专门的get,set 方法。

    1. // Sets
    2. var s = new Set();
    3. s.add("hello").add("goodbye").add("hello");
    4. s.size === 2;
    5. s.has("hello") === true;
    6. // Maps
    7. var m = new Map();
    8. m.set("hello", 42);
    9. m.set(s, 34);
    10. m.get(s) == 34;
    11. // Weak Maps
    12. var wm = new WeakMap();
    13. wm.set(s, { extra: 42 });
    14. wm.size === undefined
    15. // Weak Sets
    16. var ws = new WeakSet();
    17. ws.add({ data: 42 });
    18. // Because the added object has no other references, it will not be held in the set

    Proxies

    Proxies能用主对象的全部可用行为来创建对象,常用于监听、对象虚拟化、日志/分析等等

    1. // Proxying a normal object
    2. var target = {};
    3. var handler = {
    4. get: function (receiver, name) {
    5. return `Hello, ${name}!`;
    6. }
    7. };
    8. var p = new Proxy(target, handler);
    9. p.world === 'Hello, world!';
    1. // Proxying a function object
    2. var target = function () { return 'I am the target'; };
    3. var handler = {
    4. apply: function (receiver, ...args) {
    5. return 'I am the proxy';
    6. }
    7. };
    8. var p = new Proxy(target, handler);
    9. p() === 'I am the proxy';

    所有运行时的可行元操作如下:

    1. var handler =
    2. {
    3. get:...,
    4. set:...,
    5. has:...,
    6. deleteProperty:...,
    7. apply:...,
    8. construct:...,
    9. getOwnPropertyDescriptor:...,
    10. defineProperty:...,
    11. getPrototypeOf:...,
    12. setPrototypeOf:...,
    13. enumerate:...,
    14. ownKeys:...,
    15. preventExtensions:...,
    16. isExtensible:...
    17. }

    Symbols

    对象其实是键值对的集合,而键通常来说是字符串。而现在除了字符串外,我们还可以用symbol这种值来做为对象的键。Symbol是一种基本类型,像数字,字符串还有布尔一样,它不是一个对象。Symbol 通过调用symbol函数产生,它接收一个可选的名字参数,该函数返回的symbol是唯一的。之后就可以用这个返回值做为对象的键了。Symbol还可以用来创建私有属性,外部无法直接访问由symbol做为键的属性值。

    1. var MyClass = (function() {
    2. // module scoped symbol
    3. var key = Symbol("key");
    4. function MyClass(privateData) {
    5. this[key] = privateData;
    6. }
    7. MyClass.prototype = {
    8. doStuff: function() {
    9. ... this[key] ...
    10. }
    11. };
    12. return MyClass;
    13. })();
    14. var c = new MyClass("hello")
    15. c["key"] === undefined

    Math + Number + String + Array + Object API

    对Math,Number,String还有Object等添加了许多新的API。

    1. Number.EPSILON
    2. Number.isInteger(Infinity) // false
    3. Number.isNaN("NaN") // false
    4. Math.acosh(3) // 1.762747174039086
    5. Math.hypot(3, 4) // 5
    6. Math.imul(Math.pow(2, 32) - 1, Math.pow(2, 32) - 2) // 2
    7. "abcde".includes("cd") // true
    8. "abc".repeat(3) // "abcabcabc"
    9. Array.from(document.querySelectorAll('*')) // Returns a real Array
    10. Array.of(1, 2, 3) // Similar to new Array(...), but without special one-arg behavior
    11. [0, 0, 0].fill(7, 1) // [0,7,7]
    12. [1, 2, 3].find(x => x == 3) // 3
    13. [1, 2, 3].findIndex(x => x == 2) // 1
    14. [1, 2, 3, 4, 5].copyWithin(3, 0) // [1, 2, 3, 1, 2]
    15. ["a", "b", "c"].entries() // iterator [0, "a"], [1,"b"], [2,"c"]
    16. ["a", "b", "c"].keys() // iterator 0, 1, 2
    17. ["a", "b", "c"].values() // iterator "a", "b", "c"
    18. Object.assign(Point, { origin: new Point(0,0) })

    更多信息见文尾的ES6 API扩展的链接。

    二进制和八进制

    ES6中新增了两种数字文字:binary (b) 和 octal (o),分别用前缀0b和0o表示。

    1. 0b111110111 === 503 // true
    2. 0o767 === 503 // true

    Promises

    Promises是处理异步操作的一种模式。当你发起一个异步请求,并绑定了.when(), .done()等事件处理程序时,其实就是在应用promise模式。

    1. function timeout(duration = 0) {
    2. return new Promise((resolve, reject) => {
    3. setTimeout(resolve, duration);
    4. })
    5. }
    6. var p = timeout(1000).then(() => {
    7. return timeout(2000);
    8. }).then(() => {
    9. throw new Error("hmm");
    10. }).catch(err => {
    11. return Promise.all([timeout(100), timeout(200)]);
    12. })

    相关文章:
    ES6语言规范:ECMAScript® 2015 Language Specification
    ES6介绍:ECMAScript 6 介绍
    ES6兼容情况:compat-table-es6
    ES6草案:es6-draft
    ES6 API扩展:es6_api_extension
    Promise对象:Promise对象
    js异步编程:js异步编程的4中方式
    ES6 解构:Getting Started with JavaScript ES6 Destructuring

    淡忘~浅思猜你喜欢

    大学那些事(6)

    PHP:6种GET和POST请求发送方法

    6个Python性能优化技巧

    trick:CSS 3+checkbox实现JQuery的6个基本动画效果

    必看的 jQuery性能优化的38个建议
    无觅

    转载请注明:淡忘~浅思 » ECMAScript 6新特性介绍



沪ICP备19023445号-2号
友情链接