發表文章

目前顯示的是 五月, 2012的文章

簡單理解 JavaScript 的記憶體管理機制

不像其他的語言,JavaScript 開發者永遠沒有辦法自己去釋放記憶體,頂多只能移除物件的 Reference (代表這物件已經沒有人在使用),而且這物件所佔的記憶體並不會馬上被釋放,而是 Garbage Collection 在滿足某些條件的情況下,才在背景自動去尋找沒有被使用的物件,然後釋放。若你嘗試過尋找釋放記憶體或移除物件 Reference 的方法,得到的解答,應該不外乎是使用 delete 關鍵字或是將變數設為 null,但是你真的了解它的意義嗎?事實上,有很多人都是在不瞭解的情況下使用它們,還可能因此產生 Memory leaks 的狀況。欲弄清楚這一切,我們必須先簡單理解一下 JavaScript 的記憶體管理機制,更準確的說,是物件的管理機制。

從 JavaScript 開發者角度來看,JavaScript Engine 在運作時,記憶體使用是呈現樹狀結構,也就是所有命名或建立的變數或物件,都是存放在一個全域(global)的 Object 中。在 Node.js 中,你可以直接讀取 global 變數看到目前 Context 的環境狀態:
console.log(global);
我們可以做個實驗理解一下:
var myVar = 'Hello'; function myFunc() { return 123; } var myObj = { a: 1, b: 2 }; console.log(global);
執行以上程式,你應該可以從 global 中找到我們自己定義的變數和函式:
{ ...(已省略基本預設的環境變數)... myVar: 'Hello', myFunc: [function], myObj: { a: 1, b: 2 }, ... }
從結果可以發現,所有的物件都以樹狀的形式被 global Object 保存著,無論是變數還是任何一種類型的物件,都是一組組 Key/Value 的存在。而 Value 就是各種不同形態的物件,如字串、函數、陣列、數值等。

所以,移除某物件的 Reference,就意味著將把物件從這棵樹上拔除掉。因此,我們可以直接將該變數設為 null:
myVar = nu…

【JSDC.tw 2012 簡報檔釋出】Non-MVC Web Framework

由於一些因素,被徵招去救火,在 JSDC.tw 2012 (JavaScript Developer Conference 2012) 給與了一場 Talk,由於準備時間相當緊迫,就把最近在研究和試驗的半成品匆匆拿上場展示和說明,題目是『Non-MVC Web Framework』。你可能在議程上沒有看到這場 Talk,實際上是因為主辦單位的一些小疏忽,議程上仍是寫著之前的舊題目『Build Node.js Module』,而且小弟的名字也打錯了,從 Fred 變成了 Frend,差一點就變成二十世紀少年的友民黨教主。:-)

本次議程其實和前幾天發的舊文『前端工程師也可以淡定的開發網站應用!RedTea Web Framework!』息息相關,探討的是改善 MVC 的開發流程,和引入 JavaScript/Node.js 後的大膽嘗試,而且進一步討論實作細節。此外,因為 RedTea 本身只是一個實驗性的專案,目的只在於驗證可行性,還不到實際使用程度,所以藉著這次機會,公開並宣布新專案『Kamalan Web Framework(葛瑪蘭)』,Kamalan 引入了 Express Web Framework 為基礎,然後將結合 RedTea 的成果,並更進一步簡化其中細節和使用方法,讓前端工程師能真正無痛上手。


雖然還沒完全將 RedTea 的機制完全整合進 Kamalan,但目前 Kamalan 最少可以和 Express 一樣使用,你如果有用 Express 寫的程式,直接將 require() 引入的模組名改成 Kamalan 即可。由於 Kamalan 在根本上就是 Express,甚至是可以使用 Express 的所有 Middleware。

後記

這場 Talk 後,引起了一些 JavaScript Developer 趕的迴響,一些建議和聽眾的期待相當令人開心,討論過程也非常愉快。感謝大家的參與。:-)

【GNOME.Asia 2012】Enjoy Writing a Modern Desktop Application in JavaScript

圖片
依稀記得,當年去越南(Vietnam)參加 GNOME.Asia Summit 2009 的情景,當時甚至寫了一篇[遊記心得]。因為那是首次以講者身份參加國外的 Open Source 研討會活動,意義非凡。更重要的是,那也是當時和 Penk 組成的 ULLab(/usr/local/lab) 第一次出征,如今這樣的組合雖不復存在,但仍在心中藏有很多回憶。


今年度的『GNOME.Asia Summit 2012』將在 6/9 - 6/10 於香港舉行,很感謝 GNOME Foundation 再次贊助,讓小弟幸運的又能以講者身份飛去參加這次活動,而這次要給予的主題是『Enjoy Writing a Modern Desktop Application in JavaScript』。

今日科技變革相當快速,但桌面應用的開發一直跟不上節奏,原因是『開發效率差』和『入門門檻高』一直都是 C/C++ 這類中低階的語言的痛處,不足因應這個時代對應用的大量需求。因此使用有高生產力的腳本(Script)語言來開發桌面應用程式,便是目前可行的解決之道。

JavaScript 自 World Wide Web 澎渤發展以來,一直處於相當重要的地位,用於處理 User Interface 的工作,已經有快要二十年的時間,可說是非常成熟。事實上,GLib/GTK+/Clutter 等底層的事件模型,就與 JavaScript Engine 本身的機制大同小異,在同樣解決使用者介面的工作上,可說是殊途同歸。因此,有這樣豐富的前線作戰經驗當後盾,我們可以確信,JavaScript 非常適合被用於開發桌面應用程式。若是與 GTK+/Clutter 這類底層 Toolkit 相結合,跳脫出瀏覽器,寫原生的桌面應用程式也未嘗不可。

這次的議程,小弟將提及:
回顧 JavaScript 歷史和發展探討如何使用 JavaScript 開發原生的桌面應用程式(搭配 GTK+/Clutter/Mx)
既然這次活動的主角是 GNOME,主要將以探討原生的桌面程式為主,當然也會因應未來發展,提及 Web Application 的部份。

期待與香港和世界各地前來的朋友相見。:-)

前端工程師也可以淡定的開發網站應用!RedTea Web Framework!

還記得,尚未投入 Node.js 前,一直覺得 Node.js 帶來了未來,讓我們可以用 JavaScript 同時開發 Web 前端(Front-end)和後端(Back-end),等到真的投入 Node.js 後,發現雖然事實的確是如此,但由於前端和後端應用所需要的背景知識不盡相同,開發模式和概念更是大異其趣,所以,雖然同樣是使用大家熟悉的 JavaScript 語言,但前端開發者仍然不見得能夠如願地來開發後端應用。

這樣的情況讓我想起有位來台灣工作的外國朋友,曾告訴過我一個多年前發生在他身上的笑話。故事是:
他原本是個美術方面的設計師,然後,但有一天老闆對他說:『你從現在起,去做開發程式的工作吧。』 他問:『為什麼?』 老闆回答:『寫程式是用英文寫,而你又會英文,不就可以寫嗎?』
是的,同樣道理,雖然對前端工程師而言,JavaScript 是最熟悉的程式語言,而 Node.js 又可以讓你使用 JavaScript 寫整個 Web 應用,但這不代表對這些人而言,就可以輕易上手 Web service 的後端開發。要真正讓前後端開發合而為一,不只是語言要統一,開發經驗也要相同才是,這才是所有 Web 開發者最期盼的事。

於是筆者基於 Node.js,開發了『紅茶(RedTea)』,這是一個和現有的網站框架(Web Framework)所不一樣的全新的嘗試。以前端開發者視角和經驗為出發點,專門設計給前端工程師上手使用的網站框架,讓前端工程師也可以『淡定』的開發網站應用。由於 RedTea 不是傳統 MVC 模型的 Framework(至於 RedTea 採用的是哪種開發模型,筆者一時也說不上來。),所以,如果你是一個已經被 MVC 涂毒已深的開發者,可能要先花點時間重新理解一下。:-)

此外,RedTea 有一個最大的特點,就是支援了在瀏覽器環境下,呼叫後端 JavaScript Class/Function 的功能,就像在使用本地端的 JavaScript 物件般。因此,前後台交換資料,不用再以 GET/POST、URL Path Routing 或 Ajax 相關的方法實作,只要學會怎麼使用 JavaScript Class 即可。重點是,即使你沒有任何 HTTP 通訊協定的知識,或後前後端資料處理的經驗,依然可以開發出網站程式。

當然,設計 RedTea…

想寫好 JavaScript,遞迴技能要練好

V8 JavaScript Engine 的運作,主要是以事件驅動(Event-driven)來執行所有的程式碼,如果你有開發過 GTK+ 程式的經驗,使用上應該不陌生。不過這對一般人其實相當不好理解,因為事件驅動會讓你的程式看起來像是多工在運作(如使用執行緒),所以有些人對於 JavaScript 的理解是,有些東西可以丟背景執行。

要了解事件驅動,可以先從 JavaScript 的行為說起。如果你正在使用 Node.js,你就會發現 Node.js 通常對同樣功能提供了兩個 API,分為『同步(Synchronize)』和『非同步(Asynchronize)』兩種類型。例如下面這刪除特定檔案的例子:

同步(Synchronize) API:
fs.unlinkSync('/home/fred/badfile'); ...
非同步(Asynchronize) API:
fs.unlink('/home/fred/badfile', function(err) { if (err) { console.log('Failed to delete file.'); return; } console.log('Successfully delete a file.'); }); ...
簡單觀察同步與非同步的執行結果,可以知道前者(同步)會停住並阻塞在此 API,等檔案刪除成功後才繼續下一行程式;而後者(非同步)有如將刪除檔案的工作丟到背景執行,並繼續往下一行程式執行,完全不會像同步 API 一樣停住。等刪除檔案的工作完成後,便觸發事件去呼叫 Callback function。而這樣非同步的機制就全靠事件驅動(Event-driven)來達成,雖看起來像是把程式丟到背景跑,實際上是在 JavaScript Engine 上註冊了一個事件,等到工作完成以後,事件被觸發時才接續執行 callback function。

非同步的做法通常會用在需要花大量時間的 API 上,如檔案系統、資料庫系統的操作等,以避免因為單一 API 造成整個程式鎖死或卡住不會動的問題,尤以前端和需要即時反應的工作上,特別需要。

至於這樣的事件驅動是怎麼達成的?簡單舉例,像多工…