訂閱

上次更新

March 06, 2015 08:00 PM

所有時間皆為協調世界時(UTC)。

Powered By

Planet

摩茲星球 | MozTW Planet

這邊是工作人員碎碎念的地方,您可獲得最新出爐的資訊以及最不成形的想法 :P

February 14, 2015

Othree

CSP

CSP

Communicating Sequential Processes,簡稱 CSP,和 Content Security Policy 不一樣,是用來處理非同步執行序之間溝通的一個數學模型,我最早是在 Addy Osmani 的 JavaScript Application Architecture On The Road To 2015 這篇文章裡面看到的,花了蠻多時間試著去瞭解,最近終於覺得懂一點皮毛可以紀錄一下了。

CSP 其實不是新東西,是 C. A. R. Hoare 在 1978 年就發表的論文(PDF),1985 還出了整本書來介紹,而且全文 PDF 都有在網路上,可是這本書實在太理論了,看了一點點就看不下去,只好找其它資源,發現還真的蠻少的,但是確有找到一些近幾年的實做,像是 Go 的 routine 間用 channel 溝通,或是 Clojure 的 core.async,當然 Addy Osmani 那篇也有提到 JavaScript 的部分。

根據我目前淺薄的理解,CSP 就是用 channel 的非同步溝通機制,channel 怎麼用呢,顧名思義,就是一個傳遞訊息用的頻道,不過我覺得用管線可以更精確的描述它,而且這是一個單向的管線,一邊只能傳訊息進去,一邊只能拿訊息出來,可以達成非同步的溝通最主要在於拿訊息這邊,當你在其中一個 process 中說你要跟某個 channel 拿一個訊息出來時,如果那個 channel 裡面沒有東西,則這邊的 process 就會停下來等到那個 channel 有訊息出現,這個等待的機制不同語言有各自的方法實做。

先來看看 Go 的範例吧,因為實在是比 JavaScript 的直覺多了:

package main
import "fmt"

func main() {
    messages := make(chan string, 1)

    messages <- "ping"

    msg := <-messages
    fmt.Println(msg)
}

這段程式碼是基於 Go by Example 說明 channel 的範例,程式碼很好理解,messages := make(chan string, 1)這行用 make 產生一個 channel 指派給 messages 這個變數,messages <- "ping" 表示把 "ping" 這個字串丟進去 message 這個 channel 裡面,然後 msg := <-messages 表示從 message channel 裡面抓訊息出來,丟到 msg 這個變數,:= 是指派同時宣告變數的運算子,<- 則是用來描述操作中訊息傳遞方向用的運算子,當它是箭頭就很好理解,在 Go 裡面稱為 receive operator

在第一個例子當中,因為是先送資料進去 channel 才拿出來,所以還不太有感覺,接下來看第二個例子,一樣是 Go by Example 的,這段是 Channel Synchronization 的範例:

package main

import "fmt"
import "time"

func worker(done chan bool) {
    fmt.Print("working...")
    time.Sleep(time.Second)
    fmt.Println("done")

    done <- true
}

func main() {

    done := make(chan bool, 1)
    go worker(done)

    <-done
}

這個範例稍微複雜一點,done := make(chan bool, 1) 先產生一個 done channel,然後用 go worker(done) 產生一個 concurrent routine,跑的是 worker 這個 function,內容在 main 的上面,基本上就是 sleep 一下然後傳訊息回 done channel,然後 main 最後的 <-done 就是從 done channel 拿訊息出來,先不管平行出去的 routine,通常的程式跑到這行結束,整個程式就結束關閉了,不過,就是這個不過,正常情況下,有 <-channel 的話,該 routine 程式執行到這邊就會暫停下來,直到有從 channel 裡面拿到訊息才會繼續跑下去(或是裡面已經有訊息,直接拿到就繼續往下)。

Go 的 channel 還有一些細節可以參考 Golang channels tutorial 這篇文章,其實就是一個可以跨 routine 的傳遞資料的管道,資料可以一直傳,沒有限制數量,不過還有一些相關的細節,像是 sync channel,還有 channel 的 buffer 等等。

綜合以上的兩個範例,可以歸納出來,要支援 CSP 有兩個必要條件,第一個是可以做得出 channel 物件的機制,可以放資料進去,可以拿資料出來,是先進先出機制,這部分其實不是問題,問題是第二個條件,程式碼要能跑一跑停下來等訊息然後又繼續跑下去,這可不是用 while (1) 可以處理的狀況,用 recursive function call 效能也不太好,以前的 JavaScript 是無法良好的達成第二個條件的,直到 ES6 的 async function 出現。

ES6 async function 之前有文章介紹過,這邊就不再說明,不過總之就是執行到 yield 後,這個 function call 就會先停下來,把值傳出,直到下次再次執行該 function 才會繼續往下執行,這樣停下來的機制,正好可以利用來作為 CSP 等訊息的機制,不過利用 yield 的話有一個限制,就是一定要在 async function 裡面才可以利用 channel,不像 Go 由於是建在語言裡面的,main thread 也可以跟 channel 溝通。

雖然說可以利用 async function 可以做出 CSP 的架構出來,不過要只用 async function 來寫出像 Go 那樣簡短的程式碼實在是很困難,中間還有很多機制需要補起來,所以就開始有 library 實做,目前最有名的是 js-csp,Facebook 最近的 React.js Conf 其中一場議程介紹 CSP 時也是用 js-csp 做範例,錄影在這,作為入門 CSP 我覺得是蠻不錯的一場演講:

js-csp 裡面其實做了很多事情,目前看起來像是參考 Go 來設計,例如這樣的 Go 程式碼

package main
import "fmt"
import "time"

type Ball struct{ hits int }

func player(name string, table chan *Ball) {
    for {
        ball := <-table
        ball.hits++
        fmt.Println(name, ball.hits)
        time.Sleep(100 * time.Millisecond)
        table <- ball
    }
}

func main() {
    table := make(chan *Ball)
    go player("ping", table)
    go player("pong", table)

    table <- new(Ball) // game on; toss the ball
    time.Sleep(1 * time.Second)
    <-table // game over; grab the ball
}

改成用 js-csp 寫的話就變成:

function* player(name, table) {
  while (true) {
    var ball = yield csp.take(table);
    if (ball === csp.CLOSED) {
      console.log(name + ": table's gone");
      return;
    }
    ball.hits += 1;
    console.log(name + " " + ball.hits);
    yield csp.timeout(100);
    yield csp.put(table, ball);
  }
}

csp.go(function* () {
  var table = csp.chan();

  csp.go(player, ["ping", table]);
  csp.go(player, ["pong", table]);

  yield csp.put(table, {hits: 0});
  yield csp.timeout(1000);
  table.close();
});

csp.chan 產生 channel,用 yield csp.take 代替從 channel 取訊息,用 yield csp.put 代替送訊息到 channel,然後最重要的是用 csp.go 來代替從 Go 裡面用 go 產生 routine 的操作,然後不說可能沒人注意到,js-csp 把 routine(process)、ticker 等比較底層的基礎建設都做起來了,也就是如此才能讓程式碼和 Go 的看起來這麼接近。

js-csp 基本上就是仿照 Go 的的語法來設計,只是常常需要 yield,語法還是不如 Go 來的簡潔,至於何種情境比較適合使用 CSP 呢,以 channel 的特性來說,目前看起來是常常會發生的 event 比較適合,像是常常被拿出來講的 mousemove 事件,另外就是有要分 thread 做平行運算的話也不錯,不過目前看起來是無法接上 WebWorker,主要是因為 postMessage 無法傳遞物件 instance 過去,而是會複製一份;另外因為 channel 可以關起來,所以要用來實做 Promise 也不是不行,不過就沒什麼必要如此搞就是。

講到做事件的處理,應該會有人注意到實做上的細節問題,就是要怎麼讓多個 process 去讀取同一個 channel 呢,一般而言,channel 的訊息是只能讀取一次的,就是說雖然你可以多個 process 等同一個 channel 的訊息,但是只會有一個 process 會真的拿到新的訊息,而實務上,一個事件綁了多個 handler 的情形非常常見,照 channel 的機制,應該是不能用下去的,不然就要自己管裡 handler,又多繞了一圈,事實上,CSP 模型是有一些運算可以用的,像要處理多個 handler 的問題,就可以用 mult,可以把一個 channel 轉成一對多,其它還有多對一的 share resource、Clojure 的 onto 等等,應該是想的到的情形都已經有數學模型或是不同語言的實做可以處理了,不過 js-csp 在這部分還在開發中,像是 mult 就還在 beta 階段,其實還不太能真的用,作者有說現在的介面可能會改,也因此還沒寫到文件裡面。

最後想要記錄一下 Clojure 所提出的 transducer,transducer 的目的是讓 reduce 的操作可以用 compose 來組合,什麼是 reduce 操作呢,其實包括像 map、filter 都可以算是,但是這些操作以前是無法用 function composition 來做組合的,直到有了 transducer,又加上 transducer 把處理資料的型別也 decouple 出去了,所以 channel message 也可以利用。有兩篇文章可以參考,第一篇文章是 CSP and transducers in JavaScript,這篇講得非常清楚,他是從無到有把 transducer 建構起來,我是第二次認真看這篇文章才理解的,另外一篇文章是 Transducers.js: A JavaScript Library for Transformation of Data,是 Transducer.js 的作者寫的,從不太一樣的角度來看 Transducer 這個設計,有機會再來分享詳細一點。

這篇文章其實也不算是介紹或教學 CSP on JavaScript,比較是記錄一些我花時間想辦法理解的問題,包括為什麼現在才有人用 JavaScript 實做 CSP,實際上怎麼實做,目前適用的地方,還有整理了對 transducer 的理解,如果單純是想理解 CSP,除了前面提到的文章之外,還有幾篇文章可以參考 ES6 Generators Deliver Go Style ConcurrencyTaming the Asynchronous Beast with CSP Channels in JavaScript

February 14, 2015 07:26 AM

January 31, 2015

Othree

在盲人之前的親和力

不少人還會直接把網站的親和力(無障礙)問題和盲人朋友直接連在一起,覺得應該來解除迷思一下,盲人朋友確實是最直接會想到的,各種有身心障礙人士的族群當中,盲人朋友使用電腦上網的難度也是最高的,不過在你把眼睛矇起來體驗盲人如何操作電腦之前,有不少事情是可以先做的,隨便把腦袋裡馬上想的到的列了一下:

首先是網頁的文字內容易讀性,易讀性有分兩個面向,第一個面向大家比較清楚,就是文字排版、字形挑選、顏色對比等等視覺上的易讀程度,這部分做的好的話除了對老花眼、近視或是弱視的朋友有幫助外,一般人也會受惠;另一個面向則是文字內容好不好理解的程度,如果網站上的文字說明太難懂,那就應該要用更好理解的文字來重新講一遍,或是加上圖表輔助,或是乾脆減少資訊量,通常自己看的懂,不代表別人看的懂,所以如果是重要的說明(尤其是政府網站一些流程、辦理辦法之類的),建議都要找人看過,最簡單的是找家中長輩,因為網路上理解力較低的族群中,長輩們佔不少。

第二個是操作介面好不好操作,通常是 Web App 才有這需求,一樣有不同的面向,第一個是你的操作介面應該設計的容易理解,讓人看了也不會疑惑應該點哪裡,其中一個很重要的原則是不要破壞使用者的習慣,第二個面向是有些人可能無法好好的控制滑鼠(要模擬這個比模擬盲人的情境還要難),點擊不精確,所以永遠要保留鍵盤操作的選項,如果是使用原生的輸入元件來做操作介面的話,沒有亂做什麼奇怪的事情應該是都可以用鍵盤來控制,但是如果要自己設計一個嶄新的控制元件,那記得要好好利用 WAI-ARIA 來讓鍵盤可以順利的控制,像是 Google 的 Gmail 就有完整的鍵盤操作支援,這個應該是這篇文章當中做起來最辛苦的一項吧。

第三個是表單行為,要把表單作的好填,本身是一門很大的學問,不過在深入的思考設計表單的 usability 之前,有一些很基本的功能是應該具備的,其中特別想說的是錯誤訊息的處理,使用者送出表單後,如果後端的檢查沒過被打回來,應該要伴隨著能幫助使用者更新資料的錯誤訊息,並且正確的顯示在正確的位置,不然使用者不知道發生什麼事情,除了告訴使用者哪裡有錯之外,更進一步是讓使用者能把輸入資料改好,例如帳號名稱有格式限制的話,就要明確的說明有哪些限制,另外表單檢查不通過之後,記得也不要把使用者剛剛填的資料清空(實做這點還需要特別記得安全性問題)。

最後一個是文件結構,正確的使用 HTML 標籤,還可以輔以 WAI-ARIA 的 role 屬性,這已經是講到爛的項目了,當然 single page application 算是特殊情形,不過只要你做的頁面還是接近傳統網頁有文字內容,有主要內容的話,把網頁的文件結構弄好還是有兩大好處的:一、SEO 的部分已經好了一大半了;二、所有輔具都可以根據你的文件結構快速的帶領使用者在文件中穿梭,不用多做什麼奇怪的導盲機制。要把這塊做好算是四點當中最簡單的,只要正確的依照語意使用 HTML 標籤,不夠的再看看 WAI-ARIA 有沒有可用的 role,不要亂用標籤,然後用檢視原始碼的功能看看好不好看,如果你能開始從 HTML 原始碼中感受到美感甚至有完美的感覺出來,相信你就在正確的方向上了。

其實以上四點都有一個特色,就是把這些地方做好,不只是身心障礙人士會受惠,文字易讀性就不用說了,操控介面如果支援鍵盤,有些正常人操作起來會更得心應手,表單的訊息也是不論是怎樣的使用者都很需要,而文件結構也是,弄得好的話,大家都好找到資料,站長應該也開心。所以其實在你想要為了提升親和力而去實際模擬身心障礙人士使用電腦的情境之前,是有很多東西是可以先做的,

相信還是有人會有興趣盲人朋友怎麼操控電腦的,曾經 HappyDesigner 有邀請有聲書協會的朋友來介紹,不過已經有點久了,我去年初剛好有機會在 Moztw Lab 遇到 Fancy 示範,當時有簡單的錄下來,有興趣的朋友可以看一下:

至於要怎麼體驗盲人怎麼操作呢?如果你是用 OSX 的話,系統有內建 Voice Over,品質很好,可以直接使用,Windows 有好幾套商業軟體,至於免費的比較有名的是 NVDA,這套也是開源軟體,一開始可能需要先當明眼人練習操作,另外它講的話一開始可能會聽不太懂,聲音合成引擎和商業軟體比起來有差,多聽幾次慢慢就聽的出來再講什麼了。

January 31, 2015 10:58 AM

January 30, 2015

MozLinks-zh

Firefox for Android 的兩個新功能

我們很高興的在此公佈兩個超棒的 Android 版 Firefox 新功能:

  1. 家,甜美又能任意裝潢的家
    以您喜歡的方式安排您的首頁。新增最愛的面板到您的首頁,選擇您預設的面板、或隱藏不需要的。

  2. 快速分享按鈕
    現在您只需要輕輕的按一下分享按鈕,就可以透過您最愛的社交應用程式,快速又容易的分享網頁。(編按:而且 Firefox 還會記住你最愛使用的服務,並放到選單的最上方!)

請確保您已擁有最新版的 Firefox Android 版,或現在就立即下載。這樣,您就能享受一切最新的功能!

原文 / Two new features for Firefox for Android
授權 / 創用 CC 姓名標示-相同方式分享-3.0

φ 歐西里斯 翻譯 - Irvin 編輯

by Irvin Chen (noreply@blogger.com) at January 30, 2015 05:46 PM

January 26, 2015

orinx

準備啟程至峇里島參加 CUAsia

先簡單的介紹一下 CUAsia 是什麼吧,他的全名叫做 Coworking Unconference Asia。顧名思義就是亞洲區共用工作空間的 Unconference 。大概會有 100~200 個來自各地的空間維護者,來討論關於共用工作空間的一些經營方向、理念及案例。

這次去主要是希望能夠取經,學習看看其他亞洲國家是怎麼做共用空間管理、規劃、行銷等。也許有些東西能夠來幫助我們的 摩茲工寮 成長;同時也希望能夠在第二天搶到 Unconference topic 的名額,來分享我們 摩茲工寮 是怎麼做分散式的 Keyholder 管理制度、以及我們怎麼透過空間推廣我們所熱愛的 Mozilla 精神 及開源文化。

先把這次主要想要取經的內容先列表寫下來,歡迎大家多給點意見。我在回台灣後,會找間在 摩茲工寮 辦一場簡單的心得分享。如果你有特別期待某個方向的內容,歡迎在我的部落格直接回應討論。我會在 CUAsia 的時候會特別關注這些議題的,不過我去聽/討論的東西主要還是會以能幫助 摩茲工寮 為主

  • 吸取別人的失敗經驗,哪些場地、設備、活動以及行銷方式是不合宜的?成長到最後大家各走出怎樣的路?
  • 當空間成長的速度過快(人數、甚至是場地),該有怎樣的應變措施去確保品質?
  • 怎麼樣讓共用工作空間可以「自己養活自己」,別人是怎麼做的?大家是運用了怎樣的 Business Model 在盈利、非營利的共用空間中
  • 以一個共用空間來說,跟其他公司、政府等單位合作的生態是什麼?
  • 更多… 我有思考到我會再更新上來 :P

by Orin Chen at January 26, 2015 04:04 PM

January 23, 2015

MozLinks-zh

Firefox 附加元件下載突破四十億次啦!

正因有這些令人讚嘆的附加元件,「客製化」成為許多人選擇 Firefox 作為獨立瀏覽器的理由。數字會說話:

  • 有 18,000 個附加元件可供使用
  • 有 369,000 個佈景主題在藝廊中等著你
  • 自 2009 年統計起,捐獻給開發者們的金額已達兩千萬台幣(USD $634,000)
  • 附加元件下載突破 4,000,000,000,四.十.億.次!(大聲歡呼)

多麼「個人化」!在此我們不只為貢獻心力開發超讚 Firefox 附加元件的人歡呼,也要為使用這些附加元件的你們歡呼。今天就來看看最新的附加元件,然後替你的 Firefox 加上一些厲害的功能吧!

原文 / Firefox Add-ons Hit 4 Billion Downloads | The Den
授權 / 創用 CC 姓名標示-相同方式分享-3.0

φ Wildsky 翻譯 - Irvin 編輯

by Irvin Chen (noreply@blogger.com) at January 23, 2015 06:24 AM

January 16, 2015

Othree

fetch 二三事

之前介紹過 fetch 之後過了一段時間,有發現幾個目前 spec 上的一些細節要來分享一下。首先是上一篇文章說到的重複 header 的問題,詳細看下去後,發現 fetch 收的 header 參數有兩種,一個是 key value pair 的原生物件,另外一種是 Headers 物件,這個物件是 fetch spec 裡面新定義的:

var h = new Headers();
h.append('X-Custom-Header', '1');
h.append('X-Custom-Header', '2');
h.append('X-Custom-Header', '3');

就可以像這樣用 append 重複加上同樣名稱的 Header,其實丟原生的物件進去,也會在內部被轉成這個 Header 物件。

第二個要說的是關於回應 status code 在 400 到 600 之間時,Promise 物件是 resolve 不是 reject,理由是 Error 和 Exception 不一樣,不過有人開 Issue 在討論,會不會有改變還不知道,倒是如果現在用 github polyfill 想要處理這個問題的話,除了可以自己處理之外,也有人寫了 fetcher 這個,wrapper 可以把 fetch 的一些行為弄得更接近大部分開發者的直覺,目前提供的功能除了這個之外,還有一個是如果回傳的 type 是 JSON,但是內容的 JSON 語法有錯,那也會被丟到 reject 那邊去。

January 16, 2015 04:31 AM

January 07, 2015

MozLinks-zh

重修 Mozilla 資料隱私原則

對於資料運用透明化的承諾,是 Mozilla 的核心特質。我們設立的「資料隱私原則(Data Privacy Principles)」中,清楚的傳達了這份信念。這份在 2011 年首度釋出的原則,是 Mozilla 宣言 的補充資訊,作為我們處理資料時的指引。

今年稍早,我們重新檢視了這份原則,也邀請 Mozilla 跨部門的成員與公眾提供意見。我們將在此公開新版的 Mozilla 資料隱私原則。

這項更新反應了 Mozilla 內外的改變。自 2010 年以來的四年間,Mozilla 成長、發展出過去未有的新產品和服務。在 2014 年的 Snowden 事件後,公眾對於使用者掌控與透明化表達的強烈要求,也成為我們重新檢視產品和與隱私政策的契機。

Mozilla 資料隱私原則,將持續在創造產品、發展服務、管理用戶資料、挑選合作夥伴並與其互動時,作為我們的指引,形塑我們的公開政策與倡議行動。

Mozilla 的五個資料隱私原則為:

沒有意外
以透明與益於用戶的方式使用與共享資訊。

使用者掌控
提倡及運用最佳的典範實務作法開發產品,讓使用者得以掌控他們的資料與線上體驗。

有限資料
只收集需要的資料,盡可能的去身分識別化,並在不再需要時刪除。

合理的設定
在安全性和用戶體驗間取得合理平衡。

深度防禦
維持多層次的安全防護機制,其部分需可被公開驗證。

結合 Mozilla 宣言,當我們為使用者和網路奮鬥時,這份原則將持續指引我們的作為。為維持網路的自由和開放,我們透過透明化及給予掌控權,將使用者置於中心;透過限制資料的收集、合理設定以及強力的防護,將使用者可能遭遇的風險降至最低。

原文 / Mozilla’s Data Privacy Principles Revisited | Mozilla Privacy Blog
作者 / Denelle Dixon-Thayer
授權 / 創用 CC 姓名標示-相同方式分享-3.0

φ 張瑞明、Irvin 翻譯

by Irvin Chen (noreply@blogger.com) at January 07, 2015 01:44 PM

January 05, 2015

Othree

Android L WebView Fullscreen API

今天遇到一個問題是,本來好好的全螢幕影片播放功能,到了 Android L 的 Facebook App 裡的 webview 瀏覽器就壞掉了,而且透過開發工具看沒有錯誤訊息出來,查了一陣子終於發現,最新的 webview 改成使用 Chrome 核心後,有些 API 雖然 Chrome 有支援,但是在 WebView 裡面是沒開啟的。

其實我本來已經有用 feature detection 的寫法了,不過這個情形實際上,requestFullscreen 是找的到,可以執行,也不會有錯誤的,只是就是什麼事情都不會發生,後來才 發現 是要用 document.fullscreenEnabled 來做判斷,這個東西我之前一直覺得在手機上都用不到的東西(桌面瀏覽器通常會先問使用者是否願意讓網頁進入全螢幕),沒想到會在這邊派上用場啊。

January 05, 2015 01:20 PM

December 29, 2014

orinx

2014 剩沒幾天了,把握機會拿今年 SUMO L10n 勳章

Screen Shot 2014-12-29 at 11.59.16 PM

SUMO 是什麼

SUMO 是相撲… 啊,其實是 Support Mozilla 的縮寫 SUMOsupport.mozilla.org。這裡面放的是 Mozilla 各種產品的技術支援,大部份的疑難雜症都能在這裡解決。不過如果你是開發者,想解決或了解更核心、底層的東西。那我會建議你去看看 MDN (Mozilla Developer Network)

L10n 是什麼?

L10n 其實就是 Localization (在地化) 的縮寫,同時他也是一種標準;用於統整一套軟體不同的語系。

為什麼這個時機

因為 SUMO 每年都會有一個勳章可以領,如果你當年度有提交十篇被審核過的文章。如果你跟我一樣,喜歡蒐集這些小東西的話。可以趕快翻譯一下 SUMO 來蒐集小勳章喔。像是我 2012 年的就沒拿到,感覺超可惜的…

SUMO Link : https://support.mozilla.org/zh-TW/

by Orin Chen at December 29, 2014 04:03 PM

December 04, 2014

Othree

關於 TypeScript

type-error

這幾年各種 compile to JavaScript language 盛行,大部分都是朝向讓程式碼更好寫的方向來前進,微軟在 2012 年也推出了 TypeScript 這個 compile to JavaScript language,不過他的方向卻不一樣,TypeScript 是一個 JavaScript 的 superset,意思就是所有的 JavaScript 都是合法的 TypeScript,而 TypeScript 多了一些語法,加入了一些新功能,不過這些新的語法完全都不用也是可以正常的寫程式,給 TypeScript compiler 編譯。

TypeScript 顧名思義,它著重的在資料型別這個部分,JavaScript 是 weak type (弱型別)的語言,寫起來算是很方便,不過這個特性卻也是一些問題的來源,首先最常見到的是因為資料型態不嚴謹而造成的 bug,第二個常被提出來的就是為了實做 weak type 而造成的 performance 下降,因此一直有一些聲音在對抗弱型別這個特性,第一個是 Douglas Crockford 先出聲的,不過一開始是從程式碼的嚴謹和可靠性來說的,因為他當時主力在 JSLint 上,所以對於可靠的程式碼的要求比較高,JSLint 一度還把這項檢查放入,後來接著 Google V8 引擎也對沒有改變型別的變數作了最佳化,然後有 TypeScript,接著未來的 ES7 也可能會加入型別宣告的語法進來,這部分似乎是 Douglas 參與推動的,然後 Google 也打算推出 AtScript 的樣子,AtScript 是 TypeScript 的 superset,更進一步增加了型別相關的特性進來。

TypeScript 是一個介於中間的語言,當然為了支援 JavaScript 不能直接把整個環境都改成強型別的,所以 TypeScript 的作法是讓形別的宣告變為可省略的,如果沒有宣告型別,則一切和以前一樣,如果你的變數有宣告型別,那個變數才會是強型別,在編譯的時候,如果把不同型別的值給它,就會跑出警告訊息,像是 JSLint 一樣。TypeScript 的型別宣告語法中,一些比較簡單的可以和程式碼一起寫:

var str:string;

可是稍微複雜一點,和物件有關係的話,就要獨立寫一段宣告的程式碼了:

interface HotkeysProvider {
    template: string;
    includeCheatSheet: boolean;
    get(combo: string): ng.hotkeys.Hotkey;
    toggleCheatSheet(): void;
}

這段宣告其實是完全獨立於程式碼的邏輯本身,全部砍掉程式也可以運作,本身不牽涉到任何邏輯,所以可以完全獨立出去,在 TypeScript 中稱為 type definition(型別定義) ,常用的副檔名是 .d.ts,感覺上很像是 C 語言的 header file,其實我對於 TypeScript 本身的發展是不太樂觀的,覺得他的佔有率永遠不會起來,但是它的型別定義這塊我到覺得是大有可為,主因是目前沒有比較在業界有使用的到型別定義的語言,寫標準所用的 WebIDL 普極度實在很低,相關的工具開發和支援實在很少,反而 .d.ts 檔知道的人比較多,編譯器也都有了,而且多虧 TypeScript 有開放原碼,事實上也有其它專案有借助 TypeScript 定義檔,像是我在用的 TernJS 這個 JavaScript 自動補完工具,就有提供一個 from_ts 工具 可以把 .d.ts 檔轉成它可以讀的定義檔案,加上有 DefinitelyType 專案,各種不同 JavaScript Library 的定義檔都已經有了,所以 TernJS 就可以利用這些資源,提供各種 Library 的自動補完支援了,不過前提是使用者要知道有這些東西,官方文件其實沒有把這塊講得這麼連貫。

除了 TernJS 的應用外,我相信這些定義檔還可以讓編輯器或是 IDE 可以提供更多的輔助功能,像是或許可以拿來產生編輯器用的 syntax 定義檔,在編寫程式時直接提出警告等等,其實現在想的到的這些功能微軟的 Visuall Studio 應該都有了,不過有個公定格式做中介還是比較方便第三方應用,雖然目前好像只有看到 TernJS 的第三方應用,有些可惜,而且微軟的 Compiler 常常偷改,TernJS 提供的 from_ts 是需要使用到一些 compiler 內部的 function 才能用的,而從我接觸 TernJS 以來,微軟至少已經改過兩次改很大造成 from_ts完全不能用的情形。

總之微軟的 TypeScript 我覺得使用人數也不會有什麼大變化,但是定義檔 .d.ts 的部分倒是比較可以期待,變成半個 JS 用的標準介面定義文件格式,競爭對手的話應該是 WebIDL 吧,不過 WebIDL 比較不親切,也不太有人去實做和推廣他的應用,ES7 的型別暗示其實是只是針對那五個基本型別為主,沒有像 WebIDL 和 TypeScript 那樣完整。

December 04, 2014 03:06 PM