星期四, 2月 16, 2017

TypeScript 學習筆記(6) – Classes

主要看這篇:Classes
大致用法跟 C#/Java 差不多,幾個特別的地方:
  1. readonly :成員可以加上 readonly 來修飾,表示是唯讀。
  2. 有 getter/setter:可以用 get/set 這兩組 accessor 讓 method 變成屬性。
    class Employee {
        private _fullName: string;
    
        get fullName(): string {
            return this._fullName;
        }
    
        set fullName(newName: string) {
            this._fullName = newName;
        }
    }
    
  3. static:類似 java/c# 那樣的用法,原本 javascript 是沒有的。
  4. abstract 修飾:可以加在 class 前面,也可以加在 method 前面,用法跟 java/C# 相似。
後面提到的 constructor functions 是一個進階技巧,不過感覺上用到機會不大。

星期三, 2月 15, 2017

TypeScript 學習筆記(5) – Interface

今天是看這篇:Interfaces
TypeScript 有 anonymous interface ,就像下面的程式一樣:
// 有點 anonymous interface 的味道
function printLabel1(labelledObj: { label: string }) {
    console.log(labelledObj.label);
}

// 也可以明確的用 interface 寫
interface LabelledValue {
    label: string;
}

function printLabel2(labelledObj: LabelledValue) {
    console.log(labelledObj.label);
}

在宣告成員時,如果加入 ? ,表示可有可無,這個寫法應該是參考了 Ruby 的作法
interface SquareConfig {
    color?: string;
    width?: number;
}

用 readonly 修飾詞則是表示唯讀
interface Point {
    readonly x: number;
    readonly y: number;
}

如果要需告一個唯讀的陣列,可以用 ReadonlyArray
let ro: ReadonlyArray = a;

我覺得 Function types 比較不是那麼直覺,不容易看懂
interface SearchFunc {
    (source: string, subString: string): boolean;
}
let mySearch: SearchFunc;
mySearch = function(source: string, subString: string) {
    let result = source.search(subString);
    return result > -1;
}
大抵來說就是 python 的 \__call\__ 或是 c++ 的 operator()。
Indexable type 也是不太直覺
interface StringArray {
    [index: number]: string;
}

let myArray: StringArray;
myArray = ["Bob", "Fred"];

let myStr: string = myArray[0];
大抵來說就是 python 的 \__item\__ 或是 c++ 的 operator[]。
要讓類別實作介面是用 implements 關鍵字
interface ClockInterface {
    currentTime: Date;
}

class Clock implements ClockInterface {
    currentTime: Date;
    constructor(h: number, m: number) { }
}

下面這例子是想要限定 ClockInterface 裡的 constructor 必須符合 ClockConstructor 規範的作法,第一眼不太容易看懂。

interface ClockConstructor {
    new (hour: number, minute: number): ClockInterface;
}
interface ClockInterface {
    tick();
}

// 傳進來的 ctor 必須符合 ClockConstructor 的規範,要有 hour 跟 minute 這兩個 number 型別的參數。
function createClock(ctor: ClockConstructor, hour: number, minute: number): ClockInterface {
    return new ctor(hour, minute);
}

class DigitalClock implements ClockInterface {
    constructor(h: number, m: number) { }
    tick() {
        console.log("beep beep");
    }
}
class AnalogClock implements ClockInterface {
    constructor(h: number, m: number) { }
    tick() {
        console.log("tick tock");
    }
}

let digital = createClock(DigitalClock, 12, 17);
let analog = createClock(AnalogClock, 7, 32);

介面也可以繼承,跟類別一樣,是用 extends,而且允許繼承多個
interface Shape {
    color: string;
}
interface PenStroke {
    penWidth: number;
}
interface Square extends Shape, PenStroke {
    sideLength: number;
}

蠻令我驚訝的是,Interface 可以繼承 class ... @_@

星期六, 2月 11, 2017

TypeScript 學習筆記(4) – 變數

JavaScript 提出了兩個新的關鍵字:let 與 const。使用 let 可以避免使用 var 的一些奇妙現象;而 const 就是跟 C 的 const 一樣,避免再次指定值給這個變數。
Variable Declarations 裡提了許多 JavaScript 使用 var 宣告變數時的奇妙現象,然後解說為什麼要改用 let。這部份我偷懶跳過去了,我的想法是,就都改用 let 吧。
另外有提到 Destructuring,就是類似 Python 的 unpack :
// JavaScript/TypeScript
let input = [1, 2];
let [first, second] = input;
Python 則是:
# Python
first, second = (1, 2)
也跟 Python 3 一樣,有取 remain items 的效果:
let [first, ...rest] = [1, 2, 3, 4];
console.log(first); // outputs 1
console.log(rest); // outputs [ 2, 3, 4 ]
Object destructuring 是個比較特別的東西,意思跟 destructuring 差不多,但對象是 object,也就是可以將 object 的某幾個屬性放到變數裡。
let o = {
    a: "foo",
    b: 12,
    c: "bar"
}
let { a, b } = o;
({ a, b } = { a: "baz", b: 101 });  // 這樣也可
也支援 remaining items 的方法:
let { a, ...passthrough } = o;
Object destructuring 還支援 default values,意思是如果 wholeObject 沒有 b 屬性時,就把 b 指定為 1001:
function keepWholeObject(wholeObject: { a: string, b?: number }) {
    let { a, b = 1001 } = wholeObject;
}
也可以應用到 function 上,我覺得這個例子比較清楚,可以應用在只取物件的某幾個屬性來使用時:
function f({ a, b } = { a: "", b: 0 }): void {
    // ...
}
f(); // ok, default to { a: "", b: 0 }
Spread 算是陣列相加的一個 syntax sugar,可以把 first, second 塞到 bothPlus 這陣列裡去:
let first = [1, 2];
let second = [3, 4];
let bothPlus = [0, ...first, ...second, 5];
也可以應用在 object 上,目前想到可以用來做 object proxy 或是 composite 之類的,不過不適合也不一定。
let defaults = { food: "spicy", price: "$$", ambiance: "noisy" };
let search = { food: "rich", ...defaults };

星期五, 2月 10, 2017

電影流水帳(2017/1/1~2017/1/11)

有村架純 #jdgmovie #jdgacter<script> 有村架純
  • 寒戰2 (IMDB, Wikipedia)。整體來說,我覺得比前集稍弱了些。
    延續上集的發展,李文彬兒子李家俊入獄,但幕後的黑手蔡元祺以劉傑輝的家人作為人質跟劉傑輝談判、斡旋,劉傑輝不得已,只能隻身押解李家俊去指定的地點,但透過同黨的幫忙,李家俊逃走,劉傑輝因此面對調查會與輿論的壓力。
    蔡元祺這時出面拉攏李文彬,說明香港政治高層的佈局計劃,要求他一起加入這行動。於是就開始利用之前的衝鋒車與調查會來鬥爭劉傑輝。調查會裡的簡奧偉覺得事情不單純,派自己好友的女兒歐詠恩去調查。而劉傑輝也不甘示弱,結合了廉政署展開警政體制外的祕密調查行動。後來歐詠恩因為調查行動而被蔡元祺人馬害死,於是簡奧偉跟劉傑輝聯手,找出蔡元祺一行人窩藏衝鋒車的地方,並展開反擊。最後,劉傑輝與蔡元祺達成協議,蔡元祺遠走國外,劉傑輝穩住自己的位置以及香港高層的穩定,李文彬則被強制退休。從最後的故事走向,似乎是會有第三集的樣子。
  • ビリギャル (IMDB, Wikipedia),台譯:墊底辣妹。之前有買書,所以特別把電影也看過一次。我覺得改編的不錯,保留了書裡的故事性,把書裡大部份教怎麼唸書的地方抽離,卻又不失味道,相當勵志的故事。
    さやか是個沒怎麼唸書的少女,在母親的支持之下,到了青田塾。青田塾的坪田老師是個特別的老師,以一對一的對談去了解並引導學生, さやか因此慢慢開始轉變,並且開始對唸書有了興趣,也對自己有了信心。
    最後,在 さやか的努力下,家裡的氣氛改變了,自己的成績也愈來愈好,順利考上了慶應大學。
  • 盜墓筆記 (IMDB, Wikipedia)。前面的劇情還可以,到了後面就走味了,而且是濃濃的腐味。
    一開始是帶出悶油瓶跟外國人反派的過節,接著鋪陳出吳邪的身世以及銅片與蛇母的祕密。經過一番交代,三叔就帶著吳邪、悶油瓶跟潘子下墓探險了。值此同時,外國人反派也派了阿寧(馬思純)帶著一群傭兵去伺機搶奪。在蛇母墓展開一場你追我奪的探險,到了最後,蛇母出現,從這邊開始,莫名其妙的帶出阿寧跟胖子(阿寧隊上的翻譯)的愛情線,悶油瓶跟吳邪的腐味。與蛇母的大戰並不順利,吳邪天真的要求外國人反派幫忙,而反派居然答應了,於是順利的逆轉局勢,消滅蛇母。三叔、吳邪跟阿寧等主角順利的逃出,悶油瓶則犧牲了,看起來是還有續集的樣子?
  • 瘋狂的賽車 (IMDB, Wikipedia)。好幾年前看過一次,這次是重看的。話說啊,維基百科裡的劇情真的寫的超清楚的。
    耿浩在一次比賽後被設計了,導致拿到的銀牌飛了,也被禁賽。他的師傅氣到中風,耿浩只能開著貨車幫人送貨過活。後來師傅在電視上看到害他們的李法拉,再次氣到從樓上滾下去,死了。耿浩為了安葬師傅,決定找李法拉討錢。
    李法拉則是想把妻子殺了,所以找了殺手二人組來動手,結果反被妻子收買,改為去修理李法拉。後來陰錯陽差的變成李法拉親手殺了自己的妻子。從台灣來的烏龍幫四人組,來中國做毒品交易,結果一直沒能做成交易。故事就在這些人裡轉來轉去,產生出一連串的巧合,到了最後,李法拉跟烏龍幫四人組死了,殺手二人組成了証人,耿浩報了仇,拿到了錢,為師傅風光大葬。

星期二, 1月 31, 2017

TypeScript 學習筆記(3) – 基本型別

今天是看這篇:Basic Types
裏面直接建議用 ES6 的 let 替代 var 了。
  • boolean:布林型態
  • number:數字型態,沒有 integer, long, float, double 之類的,只有 number,JavaScript 裡的數字都是 float。
  • string:字串
  • array:陣列,在型別後面加上 [],例如: let list: number[] = [1, 2, 3]; ,要注意的是,無法指定固定個數。
  • tuple:就 tuple ,有點像陣列,但能指定每個元素的型態,這跟 Python 不一樣。例如:
    let x: [string, number];
    let x = ["Hello", 100];
    let y: [string, number] = ["John", 200];
    y[2] = "Doe";
    console.log(y);  // 輸出 [ 'John', 200, 'Doe' ]
    
  • enum:列舉,用法跟其他語言大致相似:
    enum Color {Red, Green, Blue};
    let c: Color = Color.Green;
    // 比較特別的用法
    let colorName: string = Color[2];
    console.log(colorName);  // 輸出 Blue
    
  • any:任意型態,但要注意的是跟其他語言所指的 Object 型別不同,TypeScript 有獨立一個 Object 型別。說起來跟 C# 的 dynamic 比較相似。
    let notSure: any = 4;
    notSure.ifItExists(); // 通過編譯,因為可能在執行時期就有 ifItExists()
    notSure.toFixed(); // 通過編譯,因為可能在執行時期就有 toFixed()
    
    let prettySure: Object = 4;
    prettySure.toFixed(); // 編譯錯誤,編譯時會有 Object 型別沒有 toFixed 的錯誤。
  • void:就 void ,表示不會傳回任何東西
  • null:就 null ,可以把任何型態的變數指定為 null
  • undefined:就 undefined,可以把任何型別的變數指定為 undefined
  • never:表示絕對不會傳回變數,
    // 只會丟出例外
    function error(message: string): never {
        throw new Error(message);
    }
    // 裏面是不會結束的迴圈
    function infiniteLoop(): never {
        while (true) {
        }
    }
Type assertion ,有 C/C# 強制轉型的意味。
let someValue: any = "this is a string";
let strLength: number = (someValue).length;
// 也可以用類似 c# as 的語法
let strLength: number2 = (someValue as string).length;

您或許對這些文章有興趣

Related Posts Plugin for WordPress, Blogger...