TypeScript迅速入门与应该知道
来源:互联网 发布:godaddy 域名赎回期 编辑:程序博客网 时间:2024/05/18 01:00
TypeScript应该知道
简述:TypeScript基础知识。
链接
TypeScript 官网:http://www.typescriptlang.org
TypeScript 在线编译器:http://www.typescriptlang.org/play
TypeScript 项目地址:https://github.com/Microsoft/TypeScript
TypeScript 中文网:https://www.tslang.cn/
TypeScript 中文gitbook:https://github.com/zhongsp/TypeScript
引文:
对于入门学习来说,不应该,也不能去学习过于深入的内容。以下是TypeScript入门应该知道的基础内容:
- TypeScript的基础类型
- 变量的各种声明形式
- 接口、类、函数、存取器的定义和一些使用形式
- 迭代器
- 模块的导入与导出
[注]
Ionic 2+使用Angular2+,而Angular2+使用TypeScript,因此,不管是学习Angular2,还是Ionic,首先都应该对上诉内容有一定的掌握。
其他可选:
- 声明合并
- 命名空间
- 泛型的定义和使用
- 装饰器(需要有基本的了解,Ionic项目常见)
- 高级类型(交叉类型、联合类型等)
TypeScript的基础类型
要啃一啃
- 布尔值 boolean
- 数字 number
- 字符串 string
- 数组 Array
- 元组 Tuple
- 枚举 enum
- 任意值 any
- void
- Null 和 Undefined
- Never
说明:
- 所有未定义变量的初始值都是
undefined
- TypeScript变量的声明形式如:
let 变量名:变量类型
,实际声明则形如:let flag: boolean
- let 是var的替代品,其声明的变量有更严谨的作用域,能有效避免var带来的各种问题。
基础类型示例:
//作用:添加按钮到body标签中let putButton = function (text:string,info:any){ let button = document.createElement("button"); let p = document.createElement("p"); button.textContent = text; document.body.appendChild(button); document.body.appendChild(p); button.onclick = function() { alert(info); };}//boolean类型let flag:boolean;let flag_1:boolean = false;putButton("let flag:boolean;",flag);putButton("let flag_1:boolean = false;",flag_1);//numberlet PI : number = 3.1415926535897932384626433;//圆周率putButton("number>>>圆周率PI",PI);putButton("number>>>圆直径5,周长",5*PI);//字符串let str_double_quotes:string = "双引号声明string";let str_single_quote :string = '单引号声明string';let str_accent :string = `上点号声明string`;//可内嵌${表达式}putButton("string>>>"+str_accent+"${5*8}",`5*8的值:${5*8}`);//数组,两种声明方式let nums: number[] = [1, 2, 3,4];let numList: Array<number> = nums;putButton("数组[1,2,3,4]",numList.toString());//元组Tuplelet dog:[string,number] = ["蝴蝶犬",5];//元组是一个数组,允许元素类型不同dog[3] = "岁了";//数组越界不报错,因为"dog"是string|number联合类型// dog[4] = false;//错误putButton("元组Tuple",dog[0]+dog[1]+dog[3]);//enum 枚举enum Xiyouji{ 唐僧,悟空,八戒=3,沙僧,白龙马}//手动指定索引下标let tangseng:Xiyouji = Xiyouji.唐僧;let wukong:string = Xiyouji[1];//手动声明索引,左边索引从零开始let shaseng:string = Xiyouji[4];//手动声明索引,右边索引依次增加putButton("enum>>>西游记",wukong);//any 任意值let 水牛:any = "shuiniu";let shuiniu:number = 100;水牛 = shuiniu;putButton("any>>>水牛",水牛);//void 空值,只能为null或undefinedlet v:void = null;v = undefined;function f():void{ return v};//空返回值,有点奇怪putButton("void>>>",f());//null和undefined,默认情况下null和undefined是所有类型的子类型。其他类型的值一般都可以赋给它们。let undef: undefined = null;let nul: null = undefined;putButton("null和undefined","null和undefined是所有类型的子类型");//Never类型表示的是那些永不存在的值的类型//never类型是任何类型的子类型,但没有类型是never的子类型// 这意味着never可以赋值给任何类型,但没有任何类型可以赋值给never类型(除了never本身之外)let neve:never ;//初值undefinedlet go:string = neve;//never表示永远不存在值的类型function trueWhile():never{ while (true){}}putButton("never>>>",go);
详细请参考:https://www.tslang.cn/docs/handbook/basic-types.html
变量声明
说明:下文代码中的setElement(xxx,xxx)方法,其实现如下:
/此方法的作用:在body标签中追加指定元素和内容function setElement(elementName:string,contentText:any){ let e = document.createElement(elementName); e.textContent = contentText; document.body.appendChild(e);}
关键字
应该有所了解并能使用,开始时可以不必深入研究。
- var
- const
- let
var声明的变量,可以在包含它的函数,模块,命名空间或全局作用域内部任何位置被访问。也就是说即使是这样也可以正常执行:
gog = "迷你";var gog;if (true){ alert(gog);}
const 常量,与let具有相同的作用域。
let声明的变量具有块级作用域,也就是说被try,if,while等块包围时,外部不能访问。可以有效避免var定义的各种问题。JavaScript本身具备let,IE11支持,参考:https://msdn.microsoft.com/zh-cn/library/dn263046(v=vs.94).aspx
遍历一个字符串数组,var的声明:
function forStrVar():void { let str: string[] = ["草原", "一万只尼玛兽呼啸而过"]; for (var i = 0; i < str[0].length; i++) { setElement("p", "------" + str[0].charAt(i) + "------"); //里层第一次循环完毕后,i==str[1]的长度-1,覆盖外层循环,导致外层循环条件为false,于是外层循环只执行一次。 for (var i = 0; i < str[1].length; i++) { setElement("p", str[1].charAt(i));//contents += str.charAt(i);//var声明的i互相干架。 } }}
改为let声明后正常。
数组的解构
应该了解,但可以先囫囵吞枣
解构数组,构造数组。
//数组的解构let input = [1, 2];let [first, second] = input;//相当于使用索引声明两个变量first = input[0];second = input[1];setElement("h1","数组的解构");setElement("p",first+"----"+second);//交换值[second,first] = [first,second];setElement("p",first+"----"+second);//...的形式声明剩余变量。let [o,,u,...t] = [1,2,3,4,5];//一些元素可以不必命名setElement("p",o+"----"+u+"----"+t);
对象的解构
应该了解,但可以先囫囵吞枣
类似数组的解构。JavaScript对象就是json。
let abc = {a: "foo", b: 12, c: "bar"}//符号:在此处的作用不是声明类型,而是声明属性的值。let {a,b} = abc;//虽然abc的属性更多。
function中使用解构
function()中也可以使用解构
type C = { a: string, b?: number };//符号?:表示声明一个可选的属性function f({ a, b }: C): void {//....}
展开数组
应该了解。
在声明中展开一个数组的值构成一个新的数组:
let num_a = [1,2,3];let num_b = [...num_a,4,5,"hao"];//使用“...数组”展开为元组let num_c = [num_a,4,5,"hao"];//展开setElement("h1","展开数组")setElement("p",num_b);
展开对象
应该了解
在声明中展开一个对象的值构成一个新的数组:
let dog = {id:1,name:"dog"};let home = {father:"da",monther:"mo",me:"hao",...dog,name:"狗狗阿里"};//使用"...对象"写法展开。后声明的属性允许覆盖setElement("h1","展开对象");setElement("p",home.name);
更多请参考:https://www.tslang.cn/docs/handbook/variable-declarations.html
接口、类、函数的定义和一些使用形式
需要基本掌握。
- 接口允许多继承
- 类不允许多继承,但类允许多实现
- 类通过set,get关键字声明存取器
- 接口对象的声明形式为let shou = <接口>{//…},而不是let shou = new 接口{//…};
以下定义Voice(声音)接口,Animal抽象类,Dog类,Cat类:
ICFMoreH.html
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>接口、类、函数的定义和一些使用形式</title> <script src="ICFMore.js"></script></head><body> <input type="button" value="千年京巴" onclick="jingbaClick()"/> <p></p> <p> 输入日期: <input id="month-day" type="text" value=""/> <button onclick="okClick()">确定</button> </p></body></html>
ICFMore.ts:
/** * 接口、类、函数的定义和一些使用形式 *///声音接口interface Voice { getLanguage():string;//默认public speak(content:any):void;}abstract class Animal implements Voice{ getLanguage(): string{ return "动物世界通行语"; } abstract speak(content?: any): void;//可选参数。可选声明的形式为“修饰符 名称?:类型”}class Dog extends Animal{//private和protected不能出现在模块或命名空间元素上。此处不允许用来修饰类// constructor(public name?:string,public id:string,public age:number,public sex:string){//可选参数不允许在固定参数之前// super();// } //此处使用public,为this.xx = xx的简写。会自动创建并赋值属性 constructor(public id:string,public age:number,public sex:string,public name?:string){//不允许多个构造函数实现。。。 super(); } speak(content: any): void { alert(content); } getLanguage(): string{ return "汪星语"; }}class Cat extends Animal{ private _name: string; speak(content?: any): void { alert("喵喵!"); } //getter,setter存取器 set name(name :string){ this._name = name; } get name():string{ return this._name; }}class Home{ // let dogB:Dog = new Dog("001",4,"雌","go");//不能在此使用let,var声明 private catA:Cat = new Cat(); private dogA:Dog = new Dog("001",4,"雌","go"); private readonly tag?:string = "山顶洞人的home";//可选的、只读属性的home。可选声明的形式为“修饰符 名称?:类型” protected go(){ } play(monthDay:any){//默认public this.catA.name="我是一只喵";//需要使用this.属性来访问,直接访问不到 this.dogA.name = "我是一只汪"; console.log(monthDay); monthDay = parseInt(monthDay,10);//字符串转成十进制数字 let select = monthDay % 2; switch (select){ case 0: alert("Today,我 play with "+this.dogA.name); break; case 1: alert("Today,我 play with "+this.catA.name); break; default: alert("未知日期,我 play with "+this.dogA.name); break; } }}//北京哈巴function jingbaClick(){ let jingba:Dog = new Dog("京巴001",4,"雌"); jingba.speak("汪汪!");}function okClick(){ let home: Home = new Home(); let day = (<HTMLInputElement> document.getElementById("month-day")).value;//HTMLElement中没有value属性。需要类型断言(强转) // let day = (document.getElementById("month-day") as HTMLInputElement).value;//;类型断言的另一种方式。 home.play(day);}
另一个示例——尼玛兽
接口多继承相关。
interface SayName{ sayName(name:string):void;}interface Paobu{ pao():void;}class Nima implements SayName,Paobu{ sayName(name: string): void { alert("我是"+name); } pao(): void { alert("跑了一万公里"); }}//允许多继承interface Shou extends SayName,Paobu{ shache():void;}//尼玛兽class NimaShou implements Shou{ shache(): void { alert("尼玛兽刹车了"); } sayName(name: string): void { alert("我是尼玛兽"); } pao(): void { alert("尼玛兽奔跑了一万公里"); }}// class NimaShenshou extends Nima,NimaShou{}//Classes can only extend a single classvar shou = <Shou>{};//接口对象的形式。shou.sayName = function (name:string = '兽类') { alert(name);}shou.sayName("兽类接口");var go = <Paobu>{ pao: function () { alert("跑步");}}go.pao();
迭代器
- for
- while
for…of 和 for…in:
- for…in 迭代对象的 键 的列表
- for…of 迭代对象的 键 对应的值
具体区别:
let list = [4, 5, 6];for (let i in list) { console.log(i); // "0", "1", "2",索引}for (let i of list) { console.log(i); // "4", "5", "6",值}//普通写法for (let i = 0; i < list.length; i++) { let num = list[i]; console.log(num);// "4", "5", "6",值}
do…while和while
- while 直接循环{}中代码
- do…while 先执行了do块的代码
具体区别:
let list = [1,2,3,4,5];//箭头函数表达式。能够在函数创建时绑定this,避免一些问题。常规写法则是咋函数调用时绑定,这时的this可能并非预期。 let wheel_do = ()=>{ let i =0; do { // console.log(list[i]); htmlLog(list[i]); i++;//先执行了do块的代码 }while (i<list.length);};let wheel = () => { //简单来说就是解决this指向不明的问题。 let i = 0; while (i < list.length) { htmlLog(list[i]); i++; }}let htmlLog = function (text:any) { let e = document.createElement("p"); e.textContent = text; document.body.appendChild(e);}// wheel_do();wheel();
更多请参考:https://github.com/Mingyueyixi/TypeScript/blob/master/doc/handbook/Iterators%20and%20Generators.md
关于箭头函数:
https://github.com/Mingyueyixi/TypeScript/blob/master/doc/handbook/Functions.md
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/arrow_functions
关于TypeScript的this:
https://github.com/Mingyueyixi/TypeScript/blob/master/doc/wiki/this-in-TypeScript.md
模块的导入与导出
常用,需要掌握
关键字:
- import
- export
导入与导出涉及模块,需要有加载器才能运行起来。比如服务于Node.js的CommonJS和服务于Web应用的Require.js。
模块:
- ECMAScript 2015引入。TypeScript沿用。
- 自身有作用域。需要通过导入、导出才能够引入与使用其他模块中的内容。
- TypeScript与ECMAScript 2015中,任何包含顶级 import 或者 export 的文件(.ts文件,而不是一个类或接口)
都被当成一个模块。
导出的方式
1. 声明时直接导出
export let goHome :string = "go home";export interface Hot{//...}
2. 使用export{}语句导出
interface Hot{//...}export{Hot};//export{Hot as HotDog};//Hot作为HotDog导出,重命名。as在类型断言也有相似用法。
3. 重新导出
用于导出另一个模块的部分内容,或将多个模块一起导出。
导出一个模块的部分内容:
HotHome.ts
export let dog = "热狗";export interface Hot{ eat();}
DogHome.ts
export class Dog{ eat(){ alert("eat "); }}export {dog as nimaDog} from "./HotHome";//从HotHome模块中导出dog,重命名为尼玛dog
导出之后使用import使用它:
TestHotDog.ts
import {nimaDog as nimashou} from "./DogHome";//从DogHome模块中导入nimadog,重命名为尼玛兽class Test{ go(){ alert(nimashou); }}
多个模块一起导出:
语法:export * from "module"
示例:
export * from "./HotHome"; export * from "./DogHome";
4. 默认导出
- 一个模块仅可以有一个默认导出。其声明形式为:
export default xxx
。 - 类和函数的使用默认导出后,在导入时可以省略名字。
使用默认导出:
JQuery.d.ts
declare let $: JQuery;export default $;
导入:
App.ts
import $ from "JQuery";$("button.continue").html( "Next Step..." );
导入的方式
导入的方式和导出类似
1. 直接导入声明
import {Hot} from "./HotHome"; //从HotHome模块导入export声明的Hot接口
2. 导入声明并重命名
import {dog as nimaDog} from "./HotHome";` //从HotHome模块导入export声明的dog,重命名为nimaDog
3. 所有export声明全部导入
import * as yy from "./DogHome";//从HotHome模块导入所有的export声明,命名为,使用时通过yy调用。let nimashou = yy.nimaDog;
4. 具有副作用的导入
官方文档这么描述:
尽管不推荐这么做,一些模块会设置一些全局状态供其它模块使用。 这些模块可能
没有任何的导出或用户根本就不关注它的导出。 使用下面的方法来导入这类模块:
import "./my-module.js";
导入与导出综合示例:
使用export关键字导出写好的模块:
Email.ts
export class Email { public static dress:string; public static content:string; sendTo(dress:string,content:string){ console.log("/n寄往:"+dress + "/n内容:"+content); Email.dress = dress; Email.content = content; } received(){ console.log("/n收到:"+Email.dress+"/n内容:"+Email.content); return {d:Email.dress,c:Email.content}; }}
使用import关键字导入Email模块,并使用它:
Biaoju.ts
import { Email } from "./Email";/** * 镖局 */export class Biaoju { /** * 押镖:货物 * 押镖时要发邮件通知委托人 */ yabiao(huowu:string){ let email :Email = new Email(); email.sendTo("北京","我们今天开始押镖。"+Date.now()); console.log("押镖:"+huowu); }}
Jiefei.ts
import {Email as Feigechuanshu} from "./Email";//导入Email模块,重命名为飞鸽传书/** * 劫匪 */export class Jiefei{ /** * 收到邮件之后,开始打劫 */ dajie(){ let feige:Feigechuanshu = new Feigechuanshu(); let xin:{d:string,c:string} = feige.received();//收到信 console.log("收到飞鸽传书,来自:"+xin.d+"内容:"+xin.c); alert(`${shanzhai},呔,留下买路财!`); }}export let shanzhai = "劫机山寨";
继续引入模块,将劫匪和镖局模块引入:
testGo.ts
import {Biaoju} from "./Biaoju";import {Jiefei} from "./Jiefei";let biaoju_A = new Biaoju();let jiefei_shanzaiA = new Jiefei();biaoju_A.yabiao("百年大萝卜");jiefei_shanzaiA.dajie();
[注] 生成的是符合CommonJS规范的JavaScript代码,不能直接跑。需要加载器。
更多请参考:https://github.com/zhongsp/TypeScript/blob/master/doc/handbook/Modules.md
使用module声明模块
TypeScript使用module声明模块,就能够直接跑了。
Tuzi.ts
module Tuzi{export class Tu{ speak(){ alert("我是一只兔子"); }}}
调用模块:
TestTuzi.ts
let tu = new Tuzi.Tu();tu.speak();
使用时,要引入所有编译的JavaScript文件:
TestTuziH.html
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>兔子</title></head><body><script src="Tuzi.js"></script><script src="TestTuzi.js"></script></body></html>
运行,弹出一个“我是一只兔子”对话框。
作为入门参考,一般到此结束。
以下是可选内容链接:
声明合并:
https://github.com/zhongsp/TypeScript/blob/master/doc/handbook/Declaration%20Merging.md
命名空间
https://github.com/zhongsp/TypeScript/blob/master/doc/handbook/Namespaces.md
https://github.com/zhongsp/TypeScript/blob/master/doc/handbook/Namespaces%20and%20Modules.md
泛型的定义和使用:
https://github.com/zhongsp/TypeScript/blob/master/doc/handbook/Generics.md
装饰器:
其形式为:@xxx
,能够被附加到类声明,方法,访问符,属性或参数上。
https://github.com/zhongsp/TypeScript/blob/master/doc/handbook/Decorators.md
高级类型
交叉类型、联合类型等。
https://github.com/zhongsp/TypeScript/blob/master/doc/handbook/Advanced%20Types.md
本文相关代码地址:
https://git.oschina.net/mingyueyixi/typejs/tree/master/page/00-tsBook
- TypeScript迅速入门与应该知道
- Silverlight与WPF开发人员入门应该知道的十件事
- Silverlight与WPF开发人员入门应该知道的十件事
- typescript入门,typescript特性
- typeScript入门
- TypeScript入门
- TypeScript入门
- TypeScript 入门指南
- TypeScript入门-语法篇
- TypeScript 入门11
- typescript 快速入门
- TypeScript入门-泛型
- Typescript快速入门
- TypeScript入门01
- TypeScript入门02
- TypeScript快速入门
- 一:TypeScript入门
- 一:TypeScript入门
- 2、linux下centOS系统分区
- C语言问题:为什么可以留着数组中第一维的参数不进行说明,但是其他维数必须说明呢?
- 抽象工厂模式的“开闭原则”倾斜性
- java 直接调用python脚本,并传递参数
- OpenGL蓝宝书源码学习(六)第三章——Smoother.cpp
- TypeScript迅速入门与应该知道
- Spark常见问题汇总
- (127)渲染概述
- 微信热修复Tinker使用
- Android中Application类的全面总结
- angular--$q.all()
- LeetCode 572. Subtree of Another Tree
- Vue.js——60分钟快速入门
- 字符串置换