ECMAScript 6 at COSCUP

今天在 COSCUP 的投影片,因為前一場 delay 導致後面講的有點趕,小可惜,不過該說的都有說到了~


mozjpeg 2.0

昨天 Adobe 和 Google 聯手發表了思源黑體,算是亞洲資訊圈的一件大事,結果就把另外一個消息壓下去了,其實昨天 Mozilla 發表了 mozjpeg 2.0,這個專案的目標是在保持相容於市場上現有的 jpeg decoder 之下,想辦法讓 jpeg 檔案能夠更小,第一輪的成果發表是就是昨天的 2.0 了,結果而言平均可以讓 jpeg 圖片品質不變差的情況下減少 5% 的大小,看到這個 5% 數據讓我想到 Google 曾經推出相容於 gzip, deflate 的 Zopfli,不過 mozjpeg 應該是不用花到 100 倍的壓縮時間啦,目前 Facebook 還有贊助這個計畫的下一輪發展,也就是 3.0 的開發。mozjpeg 目前是以 c lib 的形式釋出,可惜還沒有看到有命令列工具支援,希望能帶動一波圖片最佳化工具的更新潮啊。

其實 Mozilla 在去年還有發表了一篇對於目前市場上破壞性壓縮圖片格式的品質比較,比較了 JPEG、JPEG XR、WebP 和 HEVC-MSP,結果表現不離預期,最好的是 HEVC-MSP4,這是 H.265 Profile 的靜態圖片格式,算是比較項目中最新的格式了,表現最好好像不意外,不過其實高壓縮比相對的來說解壓縮需要的運算資源就會多,所以 Mozilla 才不會完全往新技術走,而開了這個 branch,顧到相容度的前提下,盡量的減少網路傳輸,這個計畫目前看來是還會繼續發展,不知道接下來還能夠提升多少壓縮比,還蠻令人期待的。


ES6 的數字

這篇想要介紹的是 ES6 的整數規則上的一些變化,首先是parseInt,看過 JavaScript Good Part 的話都會知道,這個函數的第二個參數 radix 一定要給,不然如果遇到0開頭的字串時,會自動被當成八進位的數字,這個被人詬病許久的設計終於在 ES6 中拿掉了,未來parseInt只會自動判斷0x0X為 16 進位,不然沒給 radix 就是當 10 進位。

另外一個改變是多了可以直接表示 2 進位和 8 進位整數的語法:

bin1 = 0b11;
bin2 = 0B1000;

oct1 = 0o1199;
oct2 = 0O17;

2 進位要0b或是0B開頭,8 進位則是0o或是0O,雖然和 16 進位一樣設計,不過要注意的是parseInt目前的 spec 設計是只會自動判斷 16 進位的喔。


YAJS: Yet Another JavaScript Syntax for Vim

前陣子把我 fork 的 Enhanced Javascript syntax 大改後,乾脆改名上到 Vim Scripts 了,名字就叫做 YAJS,全名是 Yet Another JavaScript Syntax for Vim(又一個 JS Syntax),當然也有 github repo 方便安裝,為什麼這次會自己大修呢,主要的原因是想要弄支援 ES6 的一些新語法,不過剛好有一些問題也已經很久了,就一口氣處理,大概整理一下和其他版的差異如下:

  • javascript做 group name 的 prefix,如此才符合 Vim doc 的規範,並且可以直接讓SyntaxComplete使用
  • 完整重新整理過的 Web API、DOM、JS 關鍵字
  • 可以完美的和 javascript-libraries-syntax.vim 共用
  • 把許多歷史遺跡的 syntax rule 都砍掉了
  • 當然最後就是支援許多的 ES6 syntax,像是 arrow function、 method definition 等

第一點這問題很久了,我好像之前也有說過,第二個一開始弄之前有點猶豫,因為關鍵字真的很多,目前整理了大概有 1800 個上下,不過後來看到 Vim 內建的 xs 的 syntax 我就釋懷了,這個檔案有三千多行,而定義關鍵字的每行都有數個關鍵字,1800 其實還只整理了一部份,除了 Global 物件都有加上外,很多新 Spec 是還沒整理的,例如 Mozilla 為了 Firefox OS 定的那些和硬體溝通的 API 等。

第三點是我重新整理的時候才注意到的,本來我的 javascript-libraries-syntax.vim 會把.的 group 取代掉,也就是原來的 syntax rule 裡面,和.有關的東西在套用過 libraries syntax 之後就會消失,只是不太容易注意到,這次修改就讓這個問題不會發生,不過 JS 僅限於 YAJS,,其他還有 CoffeeScript、LiveScript 其實不受影響,不過是因為他們本來在.之後就沒其他的 syntax highlight 了。

第四點就是把一些不明用途或是過時的東西砍掉,最後就是 ES6 的語法了,目前大概知道會有的都已經做上去了像是 block scope、let、const、class、新的 number literal 等都支援,如果有缺什麼歡迎報 bug 摟。


ES6 Method Definition

以前在產生 function 時,一定不外乎是 function declaration:

function foo() { return; }

或是 function expression:

var foo = function () { return; }

不過在 ES6 有一種新的特殊的語法可以使用,叫做 method definition,顧名思義,這個新的語法是專門用在產生物件的 method 上用的,所以嚴格說來不是用來做 function 的,然後也因此很特別的不需要使用到 function 這個關鍵字,基本的用法通常會在 class syntax 中使用:

class foo {
  constructor() {
    //blah
  }

  fooMeth() {
    //blah
  }
}

在上面這段程式碼中,constructorfooMeth都是 method definition,其實就很接近以前的 prototype method,但是大幅簡化了語法,而除了這樣使用,還可以配合getset讓它變成 accessor function:

class foo {
  get bar() {
    return this._bar;      
  }
  set bar(v) {
    this._bar = v + this._bar;
  }
}

Accessor 其實在 ES5 就已經有了,不過因為一直被 IE 卡著所以不太有人用,而且寫起來實在也麻煩很多,以前是要用defineProperty才能定義 accessor:

Object.defineProperty(foo.prototype, 'bar', {
  get: function () {
    return this._bar;
  },
  set: function (v) {
    this._bar = v + this._bar;
  }
});

當然除了比較麻煩外,還有一個問題就是defineProperty只能用在實體物件上,所以上面的 class 範例,要做出一樣效果就要在 prototype 上使用,實在不直觀,加上defineProperty其他功能真的是很少看到使用需求,新的語法這樣設計真的是很不錯,不過看到defineProperty要在實體物件上用,就會讓人反過來想,method definition 可以不用在 class 上,而是用在普通物件上嗎?事實上是可以的,ES6 的物件語法多了簡化的寫法,其中一個就是支援 method definition,所以可以這樣寫:

var object = {
  value: 42,
  toString() {
    return this.value;
  }
};

更之前的文章