node.js 4.0 新特性

node.js 4.0 是 node.js 与 io.js 回归统一之后正式推出的第一个版本。这说明从此以后, node.js 将采用 io.js 的理念,积极跟进 v8 引擎的更新,支持各种各样的ES6新特性而不必加上 harmony 标签。测试稳定后的新特性将会成为 node.js 的一等公民。新特性未来将分成三种组别,分别是:交付、展示、进行中。分别是稳定版和公测版以及测试版的意思。

 

目前发布的 4.0 测试版有以下稳定特性:

Block scoping 块级作用域

块是指由显式或隐式{}包含起来的代码,比如 if (…) {} for (…) {} 括起来的部分即为块。在以往的标准中块是没有独立的作用域的,而是与函数体共享一个作用域。在作异步编程中有时会制造一些麻烦。ES6带来的块级作用域便是用来解决这一类的问题。

let

let 和 var 一样,是用来声明变量的,不同的时,var 是作用于函数体,而 let 则是作用于块级。请看代码:

for (var i = 0; i < 10; i++) {
  process.nextTick(function(){
    console.log(i);
  });
}
也许你会以为上面的代码会输出0到9,事实上这个只会输出10个9。因为 js 是按块级去执行代码,上面其实是先把循环0到9执行完了,再去一个个执行 nextTick 传入的函数。而每个函数引用的都是局部变量i,而这个时候i已经是9,自然就输出10个9了。 而let这个时候把 var 换成 let ,你会发现程序可以正确地输出 0~9 了,let 声明的是块级变量。也就是说每个 process.nextTick 会引用于属于它自己的 i ,而不是引用到同一个局部变量,如此一来程序便可以正确输出。 #### const const 关键字就好理解了,毕竟各种语言都有。js 一向缺少定义常量的功能,const 就是用来定义常量的。需要注意的是如果 const 定义的是一个 Array 或 Object 这样类型的变量,那变量的本身内容是可能被修改的:
const FOOBAR = { "foo": 1, "bar": 2 };
FOOBAR.foo = 3; // this is legal.
FOOBAR = { "foo": 3, "bar": 4}; // this is illegal.

function-in-block

这个应该块级函数作用域方面的特性,没有找到太多资料。目测应该与 let 是一类的意思。根据说明文档,这个东西目前还不是按ES6标准实现。未来可能会发生变化。

Class 类 (仅严格模式可用)

这个是比较重量级的新特性了,OO编程的基本元素。虽说一直以来有 prototype 这样的东西可以实现相似的功能,但定义起来毕竟别扭,虽然有很多类库帮助方便的定义类,但这样也造成各种不统一。参考起别人的代码总要费些劲。

<span class="token keyword">class</span> Square<span class="token class-name"> extends Polygon</span> <span class="token punctuation">{</span>
  <span class="token function">constructor<span class="token punctuation">(</span></span>height<span class="token punctuation">,</span> width<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>height <span class="token operator">=</span> height<span class="token punctuation">;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>width <span class="token operator">=</span> width<span class="token punctuation">;
</span>    super.name = 'Square';
  <span class="token punctuation">}

</span>  get area() {
    return this.height * this.width;
  }

  static areaEqual(a, b) {
    return a.area == b.area;
  }
<span class="token punctuation">}</span>`</pre>
很好,构造函数、属性、静态函数都有了,也不用写那么多 function ,这样定义一个类可要比以往写少很多代码了。结构明显清晰多了。

### Collection 集合

#### Map 字典

基本上这是跟 Object 很类似的类型,在 ES6 出现以前我们一向是把 Object 当作字典来使用的。那么 Map 与 Object 相比有哪些优势?我们为什么要用 Map 而不是 Object:
  • Object 是有 prototype 的,也就是说在遍历的时候要特别处理,否则 prototype 的条目也会被包含进来。当然,用 Object.create(null) 也可以避免这个问题。
  • Object 只接受 String 类型作为键(KEY),而 Map 可以接受任意类型的变量作为键,这跟Java/.NET 的字典类型行为一致。
  • Map 内部有维护一个条目数量 size ,随时可以通过 size 属性来知道字典里面条目的数量,跟Array的length差不多。而 Object 则是没有这样的东东的,只能手动一个个地算。
  • 虽然目前 Object 实际上是有序的,但根据标准,Object 并不保证 key 的有序性。而 Map 规定是有序的,按插入顺序排列。

    WeakMap 弱字典

    这个跟 Map 是类似的东西,但它的键是弱引用。在 Map 中由于键是强引用,它会阻止垃圾回收系统对键和值进行回收。弱引用的在于它不会阻止垃圾回收对键值进行删除,当程序其它引用该键的变量解除引用后,GC便会进行回收,相应的,WeakMap 中的键值对也会被删除。因为受到垃圾回收的影响,所以 WeakMap 是无法对键值进行遍历。这个貌似可以用来做缓存系统?

    Set 唯一集合

    跟数组类似,不同的是 Set 针对相同的值只存储一个,另外的区别就是不能下标引用。以往在没有 Set 的情况下只能用 Object 的 Key 来代替,有了这个,在内存占用上会更有优势,另外还有 length 的属性可供使用,方便多了。

    WeakSet 弱引用唯一集合

    这个原理上跟 WeakMap 是一样的,只不过 Map 变成了 Set

    TypedArray 强类型数姐

    如果你接触的语言够多,会发现,弱类型语言的数组和强类型的数组是很不一样的。一般的强类型语言,数组Array是长度不变的(当然类型也是固定的),而弱类型数组更像是强类型中的 List 或者 LinkList ,长度可变,可以存储任意类型的数组。随着 js 在 web Server端的崛起,人们开始需要直接通过 js 操作二进制原始数组,而 TypedArray 就是对应这个需求出现的特性。

    需要注意的是,在使用 Array.isArray 对 TypedArray 进行判断时是会返回 false 的。也就是它在本质上并非是 Array 。

    在架构上,TypedArray 分为两种层,底层是 ArrayBuffer 类型,这是一种纯粹的二进制数据,没有格式,无法直接进行操作。要对原始数据进行操作,需要通过 View 层进行,分别是 Int8Array、Uint8Array、Int16Array、Uint16Array 等类型。

    `var buffer = new ArrayBuffer(16);
    `
    `if (buffer.byteLength === 16) {
      console.log("Yes, it's 16 bytes.");
    } else {
      console.log("Oh no, it's the wrong size!");
    }
    `
    `var int32View = new Int32Array(buffer);`

    Generator 生成器

    通过 function 关键字,可以定义一个返回 Generator 的函数。Generator 某程度上跟 c# 的迭代器很相似。Generator 类似于 c# 中实现了 IEnumerable 的类。function 返回的实际上是一个 Generator 实例,这个 Generator 在 yield 的地方会将值返回给调用方,然后再继续执行后面的指令。

    `function* anotherGenerator(i) {
      yield i + 1;
      yield i + 2;
      yield i + 3;
    }
    
    function* generator(i){
      yield i;
      yield* anotherGenerator(i);
      yield i + 10;
    }
    
    var gen = generator(10);
    
    console.log(gen.next().value); // 10
    console.log(gen.next().value); // 11
    console.log(gen.next().value); // 12
    console.log(gen.next().value); // 13
    console.log(gen.next().value); // 20`
    整个 Koa.js 都是基于生成器作为中间件链接动作,说明这个特性也是重量级的特性,将来应用必然会很广。 #### Binary & Octal literal 二进制和八进制字面量
    0777 // 前面加零即为定义八进制字面量,若数字中有超过8的则视为定义十六进制字面量
    0o777 // 前面加0o即为定义八进制字段量
    0b00001111 // 前面加0b即为定义二进制字面量
    0xA0A0A0 // 前面加0x即为定义十六进制字面量

    Extended Object literal 扩展对象字面量

    这是对 Object 实便声明的一种扩展,说起来挺复杂,不如直接看代码:

    var obj = {
        // 指定 prototype
        __proto__: theProtoObj,
        // ‘handler: handler’ 简化声明方式
        handler,
        // 'toString: function()' 的简化声明方式
        toString() {
         // Super calls
         return "d " + super.toString();
        },
        // 动态属性名
        [ 'prop_' + (() => 42)() ]: 42
    };
    那么,没错,就是这么吊! #### Promises 承诺对象 那么,也就是说 bluebird 可以退休了?也好!棒子的英语水平太牛逼了,看他们的文档实在是折磨人! #### New String methods 新增的 String 方法 代替了一部份 lodash 的功能,[详情请戳这里](https://developer.mozilla.org/en-US/docs/Web/JavaScript/New_in_JavaScript/ECMAScript_6_support_in_Mozilla#Additions_to_the_String_object) #### Symbol 符号 这玩意大概是从 ruby 移植过来的概念,代表唯一且不可变的标识!嗯,太抽象了,说实话一直不太喜欢 ruby 的这种设定。有什么特别实用的地方吗?看 mozilla 的文档,貌似可以用来将一些信息隐式存储到 Object 实例中。因为 for in 和 Object.getOwnPropertyNames 都不会返回 Symbol 类型的键。由于唯一性,new Symbol('foo') != new Symbol('foo'),[详情还是戳这里](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol),大家发现有什么应用的地方可以参详一下。 #### Template String 模板字符串 来自 Perl、Shell Script、PHP的精华!通过反引号``介单,可以跨行,支持变量自动替换。很实用的新特性。 ES5代码:
    `var a = 5;
    var b = 10;
    console.log("Fifteen is " + (a + b) + " and\nnot " + (2 * a + b) + ".");
    // "Fifteen is 15 and
    // not 20."`

    ES6代码:

    <span class="token keyword">var</span> a <span class="token operator">=</span> <span class="token number">5</span><span class="token punctuation">; </span>var b = 10; console<span class="token punctuation">.</span><span class="token function">log<span class="token punctuation">(</span></span>Fifteen is ${a + b} and
    not ${2 * a + b}.<span class="token punctuation">)</span><span class="token punctuation">;</span>

    可以看到代码量又显著减少了。各种喜闻乐见啊有木有。

    Arrow Function 箭头函数

    可以说这个是我个人最喜欢的新特性了,能少打几个字不说,代码看起来也更简练直观!

    `var a = [
    “Hydrogen”,
    “Helium”,
    “Lithium”,
    “Beryl­lium”
    ];

    var a2 = a.map(</span>function(s){ return s.length }); //es5
    var a3 = a.map(</span> s => s.length ); // es6

这个特性必须给五星好评。

Share Comments