说明:本系列是30天精通Angular2系列,此教程会第一时间发布在最三方平台,希望给你带来帮助!
本文出自最三方Angular系列教程,转载请注明出处!
前言
这系列标题不是 Angular2之 30天迈向神乎奇迹之路吗?怎么才第二天标题就是 TypeScript(之后简称 TS)了呢?怎么有种挂羊头卖狗肉的感觉呢?XD
先前提到 Angular2很重要的一环便是它采用 TS当作开发语言,如果 Angular是一个网页前端的精灵,那 TS就是他的灵魂啦!
事实上虽然你也可以完全使用纯 JavaScript(之后简称JS)来开发,因为 TS本身就完全兼容 JS,但身为 Super版的 JS,大家都在用了(尤其老大哥微软跟 Google),尚未成为神乎其技的我们,跟著强者的方法一起修道准没错。所以首先我们要先把 TS弄清楚,不管是语法、变量、函数、风格等等之类的,都要有所了解,这样对于之后开发 Angular只会有益无害,更何况学习新的事情是多么令人开心的事呢!
TypeScript
接著就来认识一下 TS是什么吧!
缘起
TS是为了解决 JS诸多的问题,例如资料型别(typing)、名称空间(namescpace)以及零碎的眉眉角角,而且由于当初设计 JS的阶段过于仓促,加上没有先例可以参考(第一个同时兼具函数程序和面向对象程序的语言),总总原因让大家对 JS不太满意,于是就有很多改善 JS的语言诞生,它们都希望减轻 JS开发人员的负担,改用一些结构良好或是更轻松的语言来开发应用程序(Script#、CoffeeScript),再透过各自的编译器来产出 JS程序代码, TS也是其中一个。
语法
接著就来快速入门吧!让我们看看 TypeScript有那些特殊的地方。 const & let 严格说起来这不算是 TS特殊的东西,在 ES6中对于宣告变量得更明确规范。
1 | const cannotChange = 9; // 只要改变这个常数,程序会出错 |
2 | let canChange = [{ 'a' : '1' }, { 'b' : '2' }]; //在不改变宣告的资料型别的情况下,可以改变这个参数 |
|
var虽然还是能用,但能不用尽量不要用,越明确的规范对程序帮助越好。
资料类别(typing)
以往在 JS 宣告变量是不需要宣告型别的,var 就是万能,物件可以变量字,字串可以变布林,在绝大多数的情况下,这样变来变去其实不好,虽然说不用宣告型别很方便,但就算再细心还是有出错的一天,所以 TS又强制规定要宣告型别了。 以下是所有型别范例:
02 | let decimal: number = 6; |
03 | let hex: number = 0xf00d; |
04 | let binary: number = 0b1010; |
05 | let octal: number = 0o744; |
08 | let person: string = "Mike" ; //可以用 "" |
10 | let sentence: string = `Oh, ${person} is ${age} years old.`; //也可以用 `${}` |
11 | //上面等于 "Oh, " + person + " is " + age + " years old." |
14 | let list: number[] = [1, 2, 3]; |
17 | let x: [string, number]; // Array中包含不同型别的变量用 Tuple |
18 | x = [ "hello" , 10]; // OK |
19 | x = [10, "hello" ]; // Error |
20 | x[3] = true // Error 往后的变量只能是一开始设定的 string 或 number |
|
类别注释(Type annotations)
以往在 JS中函数的参数是不需要宣告参数的型别。
JS:
1 | function greeter(person) { |
2 | return "Hello, " + person; |
|
但是这样没人知道 person是什么,到底是物件还是字串?
TS:
1 | function greeter(person: string) { |
2 | return "Hello, " + person; |
|
所以 TS强制要求参数要注释型别 person: string这样一看就知道是字串,当专案越做越大,函数呼叫函数又在呼叫下个函数,参数满天飞的时候,才不会搞错资料型别,又 debug半天才发现是资料给错!
注释也可以放入指定型态的物件,就是接下来的 Interface。
Interfaces
interface 让参数为物件时,有更明确的结构型态,而不是只是丢个参数表示为一个物件。
简单的范例应该可以让大家懂 interface 的概念。
06 | function greeter(person: Person) { |
07 | return "Hello, " + person.firstName + " " + person.lastName; |
10 | var user = { firstName: "Tiger" , lastName: "Liu" }; |
12 | console.log(greeter(user)); |
|
类别(Classes)
以往在 ES5 的 JS 是没办法像 C++、JAVA那样直接宣告类别的,JS开发者当然还是能透过一些技巧达到类似效果,但就比较麻烦也很不直观。而 ES6 版本之后 JS 加入类别的语法糖,TS 中就能用相同的方式宣告类别,编译成 JS后其实就是以前我们用来仿真类别的技巧啦!XD
03 | constructor(public firstName, public middleInitial, public lastName) { |
04 | this.fullName = `${firstName} ${middleInitial} ${lastName}`; |
13 | function greeter(person : Person) { |
14 | return `Hello, ${person.firstName} ${person.lastName}`; |
17 | let user = new Student( "Jane" , "M." , "User" ); |
19 | console.log(greeter(user)); |
|
静态成员
类别的静态成员,他的属性存在于类本身,而不是类的实例上
2 | static hands: number = 2; |
3 | static legs: number = 2; |
|
继承
有类别的概念,当然就会有继承的概念
1 | class Woman extends Human { |
2 | static gender: string = 'female' ; |
|
Interface 进阶
interface 也可以用来强制类别符合约束
05 | class Circle implements Shape { |
07 | constructor(radius: number) { |
11 | return this.radius * this.radius * 3.1415; |
|
interface 也可以继承其他的 interface
09 | interface Thing extends Color, Shape { |
|
跌代
多了 let ... of ... 的用法
4 | console.log(i); // "0" , "1" , "2" , |
8 | console.log(i); // "4" , "5" , "6" |
|
let ... of ... 的操作其实长这样
2 | for ( let _i = 0; _i < list.length; _i++) { |
|