December 29, 2012
立法院旁聽紀錄
昨天 (Dec 28, 2012) 與幾位熱衷 Open Data 的阿宅朋友一同到立法院旁聽。既然現階段的焦點放在開放政府機關的資料,走訪一趟立法院實地感受乃是必然。
政治乃眾人之事,大到國家認同,小到兒童優惠票的衡量基準,無一不與政治有關。以前視政治話題如洪水猛獸,能避則避。長大才知道政治好像氧氣,攸關生死卻沒察覺無時無刻吸著它。
害怕政治議題無非是害怕遇上有理說不清的政治狂熱者,或是跟親朋好友吵起來。我認為反倒要有盡可能清楚的論述讓大家了解議題,才可能降低不理性者的噪音。因為是親朋好友擁有互信的基礎,委婉的討論更有機會取得共識。
離題了,總之,一般市井小民願意參與政治,了解前線現況絕對是好事。做些筆記,希望給想要去立法院旁聽的朋友些許幫助。
旁聽的各種小細節散落在立法院網站各處,link 很有可能隨即失效就不貼了。基本上需要申請才方便行事(現階段,也許會有委員提出動議修改[1])
三人以上即可以團體身份在三天前送交旁聽的申請,送交的名冊會記載身份證字號,屆時進入立法院查驗身份證。立法院的工作人員告知,以團體單位送請會比較好。
一開始因為溝通有誤,我們五個人一起以個人身份進入,感受到不少關心,我想是因為平常太少鄉民會直接殺過去,一次來五人總不免會嚇一跳。會客室所讀到的申請規則,除了訂定三人以上三天前送交的規則,還有人數最高上限是一百人,我印象中並沒有閱讀到一、二人的臨時情況。沒有明定此規則,是否有什麼技術細節的問題我就不知道了。幸虧當時有黃委員的助理幫忙,讓我們順利進入旁聽。
此時我們就被請出去了
根據工作人員的說法,表決過程都能在網站上找到 (我沒找過,不確定),既然如此為何不能同時在場旁聽?工作人員沒有明白解釋。僅為走馬看花一下,沒有詳讀規則也不打算爭取些什麼,當然是十分配合地離開。不過注意到現場有幾位記者可以持續紀錄,我想媒體的優勢仍然勝過我們許多,希望他們多珍惜,而我們要多爭取。
既然走了一趟就隨手記記,並非原音呈現,僅表達接收方所被傳遞的訊息。委員的言詞有務實也有虛幻,言詞中挾著立場與想法,或是把意識形態以中立口吻掩蓋,台下雖然專注力各異,台上的表現還是要足夠專業。政治的精妙細節就是藏其中。
根據工作人員的解說,國是論壇會在 8:40 前抽籤決定,中籤委員每位可以上台發言三分鐘,三分鐘後會斷話請下台,頗有 lightening talk 的 fu。
依據上台的順序,委員的發言主旨是
[1] 黃志雄委員便在立法院第8屆第2會期教育及文化委員會第22次全體委員會議提案,根據立法院議事規則第第61條規定,各種委員會開會時,除出、列席及會務工作人員外,不得進入旁聽。此提案並未通過,可以下載會議概況表看一看,其他紀錄可以在各委員會最新消息裡面下載,該提案紀錄在更新日期 2012-12-28 的檔案之中。
政治乃眾人之事,大到國家認同,小到兒童優惠票的衡量基準,無一不與政治有關。以前視政治話題如洪水猛獸,能避則避。長大才知道政治好像氧氣,攸關生死卻沒察覺無時無刻吸著它。
害怕政治議題無非是害怕遇上有理說不清的政治狂熱者,或是跟親朋好友吵起來。我認為反倒要有盡可能清楚的論述讓大家了解議題,才可能降低不理性者的噪音。因為是親朋好友擁有互信的基礎,委婉的討論更有機會取得共識。
離題了,總之,一般市井小民願意參與政治,了解前線現況絕對是好事。做些筆記,希望給想要去立法院旁聽的朋友些許幫助。
如何申請旁聽
旁聽的各種小細節散落在立法院網站各處,link 很有可能隨即失效就不貼了。基本上需要申請才方便行事(現階段,也許會有委員提出動議修改[1])
三人以上即可以團體身份在三天前送交旁聽的申請,送交的名冊會記載身份證字號,屆時進入立法院查驗身份證。立法院的工作人員告知,以團體單位送請會比較好。
一開始因為溝通有誤,我們五個人一起以個人身份進入,感受到不少關心,我想是因為平常太少鄉民會直接殺過去,一次來五人總不免會嚇一跳。會客室所讀到的申請規則,除了訂定三人以上三天前送交的規則,還有人數最高上限是一百人,我印象中並沒有閱讀到一、二人的臨時情況。沒有明定此規則,是否有什麼技術細節的問題我就不知道了。幸虧當時有黃委員的助理幫忙,讓我們順利進入旁聽。
旁聽限制
當然不能去叫囂,畢竟不是去抗議的,而且會有人陪伴你左右隨時提供協助。不過我們只有聽到九點至十點之間的國是論壇,十點之後休息時間由於多數委員正在他室協商,直至四十分左右才開始準備法案的表決。此時我們就被請出去了
根據工作人員的說法,表決過程都能在網站上找到 (我沒找過,不確定),既然如此為何不能同時在場旁聽?工作人員沒有明白解釋。僅為走馬看花一下,沒有詳讀規則也不打算爭取些什麼,當然是十分配合地離開。不過注意到現場有幾位記者可以持續紀錄,我想媒體的優勢仍然勝過我們許多,希望他們多珍惜,而我們要多爭取。
筆記
既然走了一趟就隨手記記,並非原音呈現,僅表達接收方所被傳遞的訊息。委員的言詞有務實也有虛幻,言詞中挾著立場與想法,或是把意識形態以中立口吻掩蓋,台下雖然專注力各異,台上的表現還是要足夠專業。政治的精妙細節就是藏其中。
根據工作人員的解說,國是論壇會在 8:40 前抽籤決定,中籤委員每位可以上台發言三分鐘,三分鐘後會斷話請下台,頗有 lightening talk 的 fu。
依據上台的順序,委員的發言主旨是
- 林正二委員:請歸還馬蘭部落土地
- 李桐豪委員:關於馬總統的教育改革作為,高度肯定 12 年國教的方向,但是入學方案十分複雜,可能會造成一些階級的進入障礙,主張入學方案應通過立法院一關。
- 李貴敏委員:少年 Pi 的影片看見了台灣的實力,但是人才應該要來自世界各地,所以行政團隊應該鬆綁外來人才的政策
- 蘇清泉委員:要提昇醫療救護品質。好比提升救護車或公共場所的設備,且針對阻擾或濫用救護車的情事,修法全面加裝記錄器。
- 張慶忠委員:無設限的環境乃毒品氾濫的核心,K 他命的刑責應該比照二級毒品
- 廖國棟委員:交通部應該及期完成花東快速道路
- 詹凱臣委員:社會各界對於景氣看好的比率有大幅提昇,我們應該予以肯定。而為了避免受到國際的景氣影響....blahblah (抱歉本人才疏,除了讚揚之外抓不到重點)
- 潘維剛:頁岩氣占美國的能源比例將會大幅提昇,反觀台灣?我們沒有能源政策,朝野應該要以愛止恨,合作開創新局。
- 王育敏委員:擴大兒童優惠票,修改兒少法,以年齡取代身高,並且持續監督各單位避免民眾的福利縮水。
- 許忠信委員:國內瀰漫著自由貿易的幻想,回頭看俾斯麥時代卻是取消了自由貿易而加強工業。自由貿易要看本事,我們卻大幅開放農業及服務業,削弱台灣的工作機會。
- 張曉風委員:不需要金小刀上台,立法院就一直是個造口業的地方。每位美國總統宣示的時候,都會按著一本書發誓,是什麼書呢?是這本聖經 (接著張委員就開始讀經,直到三分鐘時間到了被斷話依然不停止,直至講完一個段落。我的宗教信仰是飛天拉麵神教,對於委員以半強迫的方式要我聆聽他教教義,本人在此提出嚴重抗議)
- 陳鎮湘委員:由於在野黨擾民,使得本會期法案通過數量最少。深感 113 遊行不妥,會破壞投資信心,我們應該要共同支持馬總統的改革。
- 陳碧涵委員:解決教育資源的「反重分配」。弱勢學生不應該因為經濟問題無法繼續升學,推內公費留學的台灣版,在台灣唸書的弱勢學生也能有獎學金補助,最快 102 年 8 月試辦。
- 邱文彥委員:台灣的石頭最美,有資源就需要保護。陸客來台後有的撿拾,有的破壞石頭,相關單位卻無法保護。
- 陳歐珀:寒凍水傷害農產,政府應該專案補助,並且及早提出因應對策,避免短期缺乏造成物價波動。
References
[1] 黃志雄委員便在立法院第8屆第2會期教育及文化委員會第22次全體委員會議提案,根據立法院議事規則第第61條規定,各種委員會開會時,除出、列席及會務工作人員外,不得進入旁聽。此提案並未通過,可以下載會議概況表看一看,其他紀錄可以在各委員會最新消息裡面下載,該提案紀錄在更新日期 2012-12-28 的檔案之中。
December 27, 2012
在 Blogger 貼上程式碼
在 blogger/blogspot 想要貼程式碼並且提供比較清晰的外觀,之前找到的方法不外乎幾種
恰好最近學了一點點 js,自己動手做很簡單的 pretty code。先定義幾個 css 格式,網頁下載完成之後,透過 javascript 對於帶有 code 類別的 pre 區塊做修改。
修改的邏輯也很簡單,僅僅只是用 regular expression 找出一些定義好的字串上點顏色罷了。我也不常貼上太多程式碼,因此正規表示式沒有寫得很認真,剛好我夠用而已。
會變成
接下來找到 javascript 的區塊貼上程式碼,請注意「這一塊不能直接貼上」,這邊是看網頁原始碼的時候看到的結果。真正要貼上的是底下那一塊
因為貼上的對象是 blogger 的 template,因此要把 & 或 < 或 > 再做一次轉換,實際上真正要貼進 blogger 的 js code 是這一段(看不懂了吧!所以我才要先貼上面比較有人性的部份XD)
- 把程式碼貼到一些 formatting tool,把程式碼轉成帶有顏色的 html code 之後再貼回 blogger
- 把 javascript 檔放到另外一個 host,開啟網頁的時候載入 js 檔對 source code 做修改
恰好最近學了一點點 js,自己動手做很簡單的 pretty code。先定義幾個 css 格式,網頁下載完成之後,透過 javascript 對於帶有 code 類別的 pre 區塊做修改。
修改的邏輯也很簡單,僅僅只是用 regular expression 找出一些定義好的字串上點顏色罷了。我也不常貼上太多程式碼,因此正規表示式沒有寫得很認真,剛好我夠用而已。
使用方法
貼上程式碼的時候為 pre 加上類別 code 即可,好比<pre class="code">
int main(void) {
printf("blah\n");
}
</pre>
會變成
int main(void) {
printf("blah\n")
}
設定方法
打開 blogspot 的設計,直接編輯 html,在 css 的部份加上這一塊pre {
margin: 5px 20px;
border: 1px dashed #666;
padding: 5px;
color: #000;
background: #f8f8f8;
white-space: pre-wrap; /* css-3 */
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
white-space: -pre-wrap; /* Opera 4-6 */
white-space: -o-pre-wrap; /* Opera 7 */
word-wrap: break-word; /* Internet Explorer 5.5+ */
}
span.control{
font-weight: bold;
color: #A00;
}
span.type {
font-weight: bold;
color: #0A0;
}
span.literal {
color: #00C;
}
span.comment {
font-weight: bold;
color: #AAA;
}
接下來找到 javascript 的區塊貼上程式碼,請注意「這一塊不能直接貼上」,這邊是看網頁原始碼的時候看到的結果。真正要貼上的是底下那一塊
onload = function () {
var elmts,
count = 0,
regLiteral = /(('.*?'|".*?"))/g, // 'foo' or "foo"
regType = /(\W|)(void|int|float|double|byte|struct)(\W)/g, // int foo
regControl = /(\W|)(for|if|fi|while|do|done|return|each)(\W)/g, // while()
regClearCmt = /(\/\*.*?)()(.*?)(<\/span>)/g,
regClearCmts = /(\/\/.*?)()(.*?)(<\/span>)/g,
regCmtsStart = /\/\*/g, //for /*
regCmtsEnd = /\*\//g, //for */
regCmt = /\/\/(.*)/g, //for //
replaceLtGt = function (pre) {
var text = pre.innerHTML;
// <a> to <a>
pre.innerHTML = text.replace(/<(.+?)>/gi, "<$1>");
},
setColor = function (pre) {
var text = pre.innerHTML;
text = text.replace(regLiteral, "$1");
text = text.replace(regType, "$1$2$3");
text = text.replace(regControl, "$1$2$3");
text = text.replace(regClearCmt, "$1$3");
text = text.replace(regClearCmts, "$1$3");
text = text.replace(regCmtsStart, "/*");
text = text.replace(regCmtsEnd, "*/");
text = text.replace(regCmt, "//$1");
pre.innerHTML = text;
};
elmts = document.querySelectorAll("pre.code"),
count = elmts && elmts.length;
while (count > 0) {
count--;
replaceLtGt(elmts[count]);
setColor(elmts[count]);
}
};
因為貼上的對象是 blogger 的 template,因此要把 & 或 < 或 > 再做一次轉換,實際上真正要貼進 blogger 的 js code 是這一段(看不懂了吧!所以我才要先貼上面比較有人性的部份XD)
onload = function () {
var elmts,
count = 0,
regLiteral = /(('.*?'|".*?"))/g, // 'foo' or "foo"
regType = /(\W|)(void|int|float|double|byte|struct)(\W)/g, // int foo
regControl = /(\W|)(for|if|fi|while|do|done|return|each)(\W)/g, // while()
regClearCmt = /(\/\*.*?)(<span class=".*?">)(.*?)(<\/span>)/g,
regClearCmts = /(\/\/.*?)(<span class=".*?">)(.*?)(<\/span>)/g,
regCmtsStart = /\/\*/g, //for /*
regCmtsEnd = /\*\//g, //for */
regCmt = /\/\/(.*)/g, //for //
replaceLtGt = function (pre) {
var text = pre.innerHTML;
// <a> to &lt;a&gt;
pre.innerHTML = text.replace(/<(.+?)>/gi, "&lt;$1&gt;");
},
setColor = function (pre) {
var text = pre.innerHTML;
text = text.replace(regLiteral, "<span class=\"literal\">$1</span>");
text = text.replace(regType, "$1<span class=\"type\">$2</span>$3");
text = text.replace(regControl, "$1<span class=\"control\">$2</span>$3");
text = text.replace(regClearCmt, "$1$3");
text = text.replace(regClearCmts, "$1$3");
text = text.replace(regCmtsStart, "<span class=\"comment\">/*");
text = text.replace(regCmtsEnd, "*/</span>");
text = text.replace(regCmt, "<span class=\"comment\">//$1</span>");
pre.innerHTML = text;
};
elmts = document.querySelectorAll("pre.code"),
count = elmts && elmts.length;
while (count > 0) {
count--;
replaceLtGt(elmts[count]);
setColor(elmts[count]);
}
};
要把「貼上 template 的醜陋內容再轉一次變成能夠貼上 blog 文章」這樣轉來轉去自己都快被搞混了,希望我沒有貼錯December 25, 2012
Momome
聖誕節的時候上傳了之前寫的一個小程式 Momome,請看 Google Play 的 Momome
這是 Open source 的程式,原始碼可以在 Github momome 裡面取得。
程式很單純,寫入一些簡單的筆記事項,以 ListView 的方式顯示。比較特別之處是,你寫入的東西會被加密儲存,讀取的時候再解開。解密需要你輸入之前設定的密碼,而且程式在關閉的時候會自動上鎖。
也就是說,設定一個密碼之後開始紀錄一些大小雜事,寫完直接離開程式即可。下一次開啟時會被詢問密碼,只有知道密碼的人才能夠看見你寫了什麼東西進去。
生活中大多數會用到的東西 Market 上頭都有了,之前還真不知道要寫什麼小程式來玩玩。
娛樂性的 app 好比遊戲,大家會在手機裡面裝好幾個性質類似的程式,我相信許多人的手機裡面就好幾個不同版本的 Angry Birds。但是寫遊戲的成本非常高,需要程式、美工與企劃,除了熱血度破表的阿宅,個體戶實在很難推出遊戲 App。
工具類 App 的生存模式就不同,即使類似功能的程式有好幾個選擇,使用者最後都只會想要「選出一個」,然後一直用到它跟不上時代為止。要在夾縫中生存就必須持續打出差異化,讓人們覺得「這個程式比較好」才會捨棄另外一個選擇。還有一種工具類程式要與後端的服務做結合,好比摩斯漢堡的點餐程式、iKala、Line 或 Whats app,人們是為了用後端的服務而選擇前端程式,角力的場所其實是後端,這種也不是個體戶的領域。
個人認為想要再寫新的 App 送上 Market,要嘛不斷整合各種功能愈寫愈大,要嘛在同質性高的族群裡頭找出貼心的小細節、或是把程式的主要功能做到最好,不然使用者很懶得換工具的。
若說大家手機裡面 80% 的程式相同,只有 20% 的程式會不一樣,把某個小細節抽出來特化到極點,對準 20% 的空間其實是個體戶的守備範圍。這個市場絕對不大,因此不會是商業應用的好對象,寫起來成本不高,又適合 Open Source 出來給大家一起改,自娛娛人的小程式針對這種方向來寫還不錯。
我也覺得,這種只專心做一件事情的小程式會愈來愈多。能夠飛天遁地的大玩意有幾隻就夠了,現實生活中每個人在小地方都很不一樣,也因此有些非常奇怪的需求並不容易被滿足,有隻 Just work 的程式滿足這種小需求真的是很貼心的事情。(這種程式麻煩的地方在於很難推銷出去給別人知道 XD)
恰好我很鼓勵老婆使用強度夠的密碼,最好還是每個網站都用不同組。但是太多複雜的密碼很難記憶,寫下來也不好。乾脆把「密碼的提示」紀錄在隨身會帶的手機裡頭,再用一組密碼去保護它,兼顧了方便性以及最低限度的安全。
這隻小程式是寫給老婆的,我自己也很常用。好比去朋友家裡偶爾要登入 Wifi,隨手把密碼紀錄到程式裡面就不需要每次都問,人家家裡的密碼用明碼記錄下來似乎不太好。
至於為什麼叫 Momome,因為老婆的外號是「桃」,而且這個程式用來當作 Memo,就取了這個簡單好記的名字。
到今天 12/25 跟老婆在一起滿三年了,老婆聖誕節快樂唷~
這是 Open source 的程式,原始碼可以在 Github momome 裡面取得。
程式很單純,寫入一些簡單的筆記事項,以 ListView 的方式顯示。比較特別之處是,你寫入的東西會被加密儲存,讀取的時候再解開。解密需要你輸入之前設定的密碼,而且程式在關閉的時候會自動上鎖。
也就是說,設定一個密碼之後開始紀錄一些大小雜事,寫完直接離開程式即可。下一次開啟時會被詢問密碼,只有知道密碼的人才能夠看見你寫了什麼東西進去。
![]() |
| 打開程式卻沒有輸入密碼,看不見任何內容 |
![]() |
| 輸入密碼解鎖 |
![]() |
| 解鎖後看見之前輸入的內容 |
生活中大多數會用到的東西 Market 上頭都有了,之前還真不知道要寫什麼小程式來玩玩。
娛樂性的 app 好比遊戲,大家會在手機裡面裝好幾個性質類似的程式,我相信許多人的手機裡面就好幾個不同版本的 Angry Birds。但是寫遊戲的成本非常高,需要程式、美工與企劃,除了熱血度破表的阿宅,個體戶實在很難推出遊戲 App。
工具類 App 的生存模式就不同,即使類似功能的程式有好幾個選擇,使用者最後都只會想要「選出一個」,然後一直用到它跟不上時代為止。要在夾縫中生存就必須持續打出差異化,讓人們覺得「這個程式比較好」才會捨棄另外一個選擇。還有一種工具類程式要與後端的服務做結合,好比摩斯漢堡的點餐程式、iKala、Line 或 Whats app,人們是為了用後端的服務而選擇前端程式,角力的場所其實是後端,這種也不是個體戶的領域。
個人認為想要再寫新的 App 送上 Market,要嘛不斷整合各種功能愈寫愈大,要嘛在同質性高的族群裡頭找出貼心的小細節、或是把程式的主要功能做到最好,不然使用者很懶得換工具的。
若說大家手機裡面 80% 的程式相同,只有 20% 的程式會不一樣,把某個小細節抽出來特化到極點,對準 20% 的空間其實是個體戶的守備範圍。這個市場絕對不大,因此不會是商業應用的好對象,寫起來成本不高,又適合 Open Source 出來給大家一起改,自娛娛人的小程式針對這種方向來寫還不錯。
我也覺得,這種只專心做一件事情的小程式會愈來愈多。能夠飛天遁地的大玩意有幾隻就夠了,現實生活中每個人在小地方都很不一樣,也因此有些非常奇怪的需求並不容易被滿足,有隻 Just work 的程式滿足這種小需求真的是很貼心的事情。(這種程式麻煩的地方在於很難推銷出去給別人知道 XD)
恰好我很鼓勵老婆使用強度夠的密碼,最好還是每個網站都用不同組。但是太多複雜的密碼很難記憶,寫下來也不好。乾脆把「密碼的提示」紀錄在隨身會帶的手機裡頭,再用一組密碼去保護它,兼顧了方便性以及最低限度的安全。
這隻小程式是寫給老婆的,我自己也很常用。好比去朋友家裡偶爾要登入 Wifi,隨手把密碼紀錄到程式裡面就不需要每次都問,人家家裡的密碼用明碼記錄下來似乎不太好。
至於為什麼叫 Momome,因為老婆的外號是「桃」,而且這個程式用來當作 Memo,就取了這個簡單好記的名字。
到今天 12/25 跟老婆在一起滿三年了,老婆聖誕節快樂唷~
December 19, 2012
Javascript 的 Object 與 Function
雖然說只要翻兩下書看幾個網站就能開始寫 code,而且看了這些東西也不見得對於寫程式有一日千里的幫助。出於阿宅很純粹的好奇心,我還是花了點時間看了 ECMAScript Q___Q
程式寫了一段時間,有時會對某一句天經地義的話沉思很久,總感覺此中有真意,欲辯「不知言」 - 不知道該怎麼解釋它,當然也有可能是庸人自擾,痴人發夢。往往好奇心就在此時被挑起,追尋了半天終於得到了一個原本就知道而且跟大家一模一樣的結論。或許此時只能用「過程比結果重要」來安慰自己。
從來沒想過自己會寫 javascript,剛碰 javascript 就讀到了不少讓人「津津樂道」的特色。好比 Hoisting 或 Closure 這種沒有在 spec 裡面出現,而是在實務中衍生出來的概念,又或著惡名昭彰的全域變數,一不小心就會跟它打上交道,看到不少說法都是因為 spec 定得不好。
這就有意思了,究竟是什麼樣的 spec 可以把一個語言搞成這樣?平常會用觀察的方式去理解一個語言的行為,但是 Javascript 的「出名」讓我有點擔憂,害怕自己觀察到的是某一個實作獨有的現象。因此才會去翻 ECMAScript 順便滿足好奇心。
好奇心被挑起之後,想要釐清以下幾個問題
接下來是一點閱讀的心得與筆記,若有疏誤請不吝指教
在 Overview 的部份對一些常見且富含多種意義的名詞做了稍微明確解釋,先記起這些名詞往後會比較順利
[[Get]] 指向一個 internal method,這個 method 需要一個參數叫 propertyName,執行的結果是回傳一個 property 的 value。
而 [[Prototype]] 就是 __proto__,至於它的值後面再說明。
此外,某些物件還有這些 internal properties
接下來更深入地看一下產生 Function object 的過程
產生 Function object 的時候,也會並為該物件設定一些 properties。好比把 [[Call]], [[Constructor]] [[Code]]。Code 的內容是 FunctionBody,[[Call]] 跟 [[Constructor]] 指向 internal method。
執行這個 function 的時候(call function),就會 invoke [[Call]],[[Call]] 指向了 built-in function,作用是拿 [[Code]] 的值來執行。
如果用 new 來執行 function,就會 invoke [[Constructor]]。spec 說 [[Constructor]] 也會去 inkvoke [[Call]],但是多了一些動作,譬如說設定 prototype,而且在 invocke [[Call]] 的時候會把 'this' 指到一開始產生的物件。
所以 new 跟平常的 function call 各自執行不同的 internal method,前者會多做一些事情,譬如說把 this 指向剛剛產生的物件,以及設定 prototype。
prototype property 跟 [[Prototype]] 是不一樣的東西。*.prototype 僅是一個 property,它什麼都可以指。而 [[Prototype]] 是 internal property,會指向 Constructor 的 prototype property,或是內建物件的 prototype property,總之就是會指向某一個物件,查找 property 的時候才有一個 chain 可以用。謹記這兩者的分別,閱讀 jQuery core 的時候會有幫助。
程式寫了一段時間,有時會對某一句天經地義的話沉思很久,總感覺此中有真意,欲辯「不知言」 - 不知道該怎麼解釋它,當然也有可能是庸人自擾,痴人發夢。往往好奇心就在此時被挑起,追尋了半天終於得到了一個原本就知道而且跟大家一模一樣的結論。或許此時只能用「過程比結果重要」來安慰自己。
從來沒想過自己會寫 javascript,剛碰 javascript 就讀到了不少讓人「津津樂道」的特色。好比 Hoisting 或 Closure 這種沒有在 spec 裡面出現,而是在實務中衍生出來的概念,又或著惡名昭彰的全域變數,一不小心就會跟它打上交道,看到不少說法都是因為 spec 定得不好。
這就有意思了,究竟是什麼樣的 spec 可以把一個語言搞成這樣?平常會用觀察的方式去理解一個語言的行為,但是 Javascript 的「出名」讓我有點擔憂,害怕自己觀察到的是某一個實作獨有的現象。因此才會去翻 ECMAScript 順便滿足好奇心。
好奇心被挑起之後,想要釐清以下幾個問題
- 什麼叫做物件
- 什麼叫做 function
- 什麼是 function call, new,constructor
- 產生新物件的過程為何
- 產生的新物件與 constructor 的關係為何
接下來是一點閱讀的心得與筆記,若有疏誤請不吝指教
4.2 Language Overview
4.2 指的是 spec 裡面的 4.2 章節,後面還會重複出現類似的數字。
在 Overview 的部份對一些常見且富含多種意義的名詞做了稍微明確解釋,先記起這些名詞往後會比較順利
- ECMAScript program
一群可以相互溝通的物件(is a cluster of communicating objects),程式就是在物件的互動之中完成功能。 - ECMAScript object 帶有一些 properties 的集合。(is a collection of properties each with zero or more attributes that determine how each property can be used)
- Properties
容器,可保有物件、函式或是 primitive value(are containers that hold other objects, primitive values, or functions.) - Primitive value
- Undefined
- Null
- Boolean
- Number
- String
- Object
內建型別 Object 的成員(is a member of the remaining built-in type Object)
- Function 可以呼叫的 object (is a callable object.)
- Method
物件的 property 如果是個 function,稱之為 method(A function that is associated with an object via a property.)
- Object object
- Function object
- Array object
- String object
- Boolean object
- Number object
- Math object
- Date object
- RegExp object
- JSON object
- Error object
- Error
- EvalError
- RangeError
- ReferenceError
- SyntaxError
- TypeError
- URIError
8.6.2 Object Internal Properties and Methods
這一章節指出,所有的物件都一定帶有某些 internal properties,這邊僅列出幾項- [[Prototype]]
- [[Class]]
- [[Get]]
- [[GetOwnProperties]]
[[Get]] 指向一個 internal method,這個 method 需要一個參數叫 propertyName,執行的結果是回傳一個 property 的 value。
而 [[Prototype]] 就是 __proto__,至於它的值後面再說明。
此外,某些物件還有這些 internal properties
- [[Constructor]] new operator 會用這個 property
- [[Call]] 單純的 function call 會使用這個 property
- [[Code]] 只有 Function Object 會有這個屬性
接下來更深入地看一下產生 Function object 的過程
13.2 Creating Function Object
先定義名詞- FormalParameterList - 參數 list
- FunctionBody - function 的內容
- 產生 native ECMASCript object, 令其名為 F
- 除了 [[Get]] 之外設定所有的 internal methods
- 把 F 的 internal property [[Class]] 設成 "Function"
- 把 F 的 internal property [[Prototype]] 設成 Function.prototype,即 built-in object Function 的prototype 屬性所指向的物件
- 把 [[Code]] 設成 FunctionBody
- 設定許多 internal properties,其中一些 property 會指向特定的 internal method,以下這兩個與 function 的行為有關
- internal method [[Call]] 被 invoke 時這一次執行的狀態放入 funcCtx。[[Code]] 這個 internal property 就是 FunctionBody,執行之後的結果回傳,且把之前的執行狀態 restore 回來。
- internal method [[Constructor]] 被 invoke 時
- 產生新的 ECMAScript object(假設叫 obj),並且設定一些 internal methods。
- 把 obj 的 [[Class]] 設成 "Object"
- 對 F 呼叫 [[Get]] property,參數是 "prototype",假設呼叫的結果叫做 proto
- 如果 proto 是一個 Object,把 obj 的 [[Prototype]] 指向該物件
- 如果 proto 不是一個 Object,把 obj 的 [[Prototype]] 指向 built-in Object 的 prototype 屬性
- 回傳值是 invoke [[Call]] 的結果並且把 this 指向新產生的 Obj 。因為 [[Call]] 其實是執行 Code,所以Constructor 與 Call 都同樣是去跑一遍 Code
Function 也是物件,只是這個物件帶的屬性有點不一樣,因此成為一個可以呼叫(callable)的物件。
產生 Function object 的時候,也會並為該物件設定一些 properties。好比把 [[Call]], [[Constructor]] [[Code]]。Code 的內容是 FunctionBody,[[Call]] 跟 [[Constructor]] 指向 internal method。
執行這個 function 的時候(call function),就會 invoke [[Call]],[[Call]] 指向了 built-in function,作用是拿 [[Code]] 的值來執行。
如果用 new 來執行 function,就會 invoke [[Constructor]]。spec 說 [[Constructor]] 也會去 inkvoke [[Call]],但是多了一些動作,譬如說設定 prototype,而且在 invocke [[Call]] 的時候會把 'this' 指到一開始產生的物件。
所以 new 跟平常的 function call 各自執行不同的 internal method,前者會多做一些事情,譬如說把 this 指向剛剛產生的物件,以及設定 prototype。
prototype property 跟 [[Prototype]] 是不一樣的東西。*.prototype 僅是一個 property,它什麼都可以指。而 [[Prototype]] 是 internal property,會指向 Constructor 的 prototype property,或是內建物件的 prototype property,總之就是會指向某一個物件,查找 property 的時候才有一個 chain 可以用。謹記這兩者的分別,閱讀 jQuery core 的時候會有幫助。
December 11, 2012
Dupcility 備份檔案
前言
寫在最前面希望比較多人看到大學時代經常看到有人在痛哭實驗室的電腦在畢業前夕失竊,心血結晶的論文一併消失。其實只要有備份的習慣就能夠將傷害降到最低,要維持備份的習慣最重要的是備份的流程要很簡單
另外,一顆隨身硬碟一千多元,比起丟失重要資料的風險,這筆成本幾乎可以忽略不計。
正文
我們用相機拍攝許多數位照片並存進電腦裡,一不小心因為硬碟的毀損或失竊,人生的重要回憶就不見了。老婆現在用 Ubuntu 當成日常使用的桌面環境(真的!),當然要為老婆找出備份的解決方案,這樣才能長久保存美美的照片。
找了一個看起來最簡單的工具就是 Deja-Dup,不論在 debian 或 ubuntu 底下一個指令就能裝起來了。
$ sudo aptitude install deja-dup
這個工具簡單到應該不需要再寫什麼,注意 Deja-dup design 的 screenshot 頁面說,開頭那個美美的保險箱畫面只會在第一次顯示(到底為什麼啊!?)
Deja-dup 只是一個前端工具,後端使用的是很棒的 duplicity,duplicity 有以下特點
- 備份的檔案會打包成一個 tar.gz 檔,因此備份的東西不會綁死在 duplicity 上面
- 漸進式的備份,存下有差異的部份
- 可以用密碼或 gpg 加密
附帶一提
- Deja-dup 僅提供密碼的對稱式加密
- Deja-Dup 在 restore 的時候,有時候顯示成功卻看不見還原的檔案,介面顯示的錯誤訊息不夠。此時通常是權限問題,譬如說要還原一個備份檔,備份檔裡面包含需要 root 權限的路徑,或是解開還原檔案的目錄本身權限有問題,檢查一下應該都可以成功
Duplicity
因為 Deja-dup 太簡單不需介紹。這邊簡述一下 duplicity 的指令用法,熟悉的阿宅直接看 man page 吧。duplicity 的 man page 可以看到兩個參數 URL 與 Directory。URL 代表的是備份檔要放置的位置,Directory 就是要被使用的目錄,兩者前後調換就會有 backup/restore 的功能。
不加密
# 不加密,把 /home/foo/files 備份到 /tmp/foo 底下
$ duplicity --no-encryption /home/foo/files/ file:///tmp/foo
# 把不加密的 /tmp/foo 備份還原到 /home/bar/files
$ duplicity --no-encryption file:///tmp/foo /home/bar/files
如果備份檔放置的目錄,有許多份 full tarball,會選擇日期最新的解開。
備份多個目錄
利用 include 與 exclude,似乎一定要兩者都有才會動。放在前面的優先權比較高,相關的解釋看 man page 的 ‘FILE SELECTION’$ duplicity --include /tmp/pathA --include /tmp/pathB --exclude '**' /tmp file:///tmp/backup
甚至可以寫到檔案裡面,globbing 指的是 pattern 能夠使用「* ** ?」這些特殊字元
$ cat list
/tmp/pathA
/tmp/pathB
$ duplicity --include-globbing-filelist list --exclude '**' /tmp file:///tmp/backup
對稱式加密
# 備份或還原時都需要輸入同一組密碼
$ duplicity /home/foo/files/ file:///tmp/foo
$ duplicity file:///tmp/foo /home/bar/files
非對稱式加密
使用 gpg 來做非對稱式加密$ gpg --list-secret-keys 先列出有哪些 key 可用,選一組如果該 key 有設定 passphrase,備份的時候不會問你 passphrase,因為是使用 public key 加密。但是在還原解開的時候會用到 private key,因此會需要 passphrase。
$ duplicity --encrypt-key THEKEYID /home/foo/files/ file:///tmp/foo
$ duplicity --encrypt-key THEKEYID file:///tmp/foo /home/bar/files
刪除過久的備份
備份多次以後會有數不清的檔案。可以再備份一次 full 然後刪除舊的檔案$ duplicity full YOUR_BACKUP_COMMAND幾個指令配合起來,寫個小 script。真的要備份的時候,只要把外接硬碟接上,執行 script 再出去喝口飲料,回來就可以把硬碟拔掉,應該夠簡單了吧?
$ duplicity remove-all-but-n-full 1 file:///path/to/repository # 列出可能會被刪除的檔案
$ duplicity remove-all-but-n-full 1 --force file:///path/to/repository # 真正刪除
Update
duplicity 備份的時候也會透過 gzip 壓縮,因此時間會長一點。如果不需要壓縮就加上參數 --no-compression。預設以 25 MB 為大小弄成一包,如果要改變這個大小就利用參數 --volsize,後接 100 就是以 100MB 為大小分割。
Subscribe to:
Posts (Atom)



