TypeScript基础语法
1.1 js与ts的区别
最大区别:js不会在赋值时检查是否与类型匹配,而ts会检查所赋的值是否与类型匹配,若不匹配则会进行报错提示
1.2 js的数据类型(两大类)
1.2.1 原始数据类型(5种)
原始数据类型:number、string、boolean、null、undefined
1.2.2 复杂数据类型(除原始类外)
复杂数据类型(引用数据类型):Object、Array、Function
1.3 ts的数据类型(11类)
1.3.1 原始数据类型
原始数据类型:number、string、boolean、null、undefined
1.3.2 复杂数据类型
复杂数据类型(引用数据类型):Array
1.3.3 其他数据类型
其他数据类型:tuple(元组类型)、enum(枚举类型)、any(任意类型)、never(never类型)、void(void类型)
1.4 ts定义数据类型
1.4.1 原始数据类型
(1)number类型:Number 对象是原始数值的包装对象
// 与js一样,ts中所有数字都是浮点数,支持十进制、十六进 制,还支持ECMAScript 2015中的二进制和八进制字面量
let num:number = 6;
let hexLiteral: number = 0xf00d;
let binaryLiteral: number = 0b1010;
let octalLiteral: number = 0o744;
(2)string类型:String 对象用于处理文本(字符串)
// 使用双引号或单引号比表示
let str:string = '你好';
str = "hello";
// 使用模板字符串表示:模板字符串可定义多行文本或内嵌表达式
let username:string = `marry`;
let all:string = `My name is ${username}`;
(3)boolean类型:
let isShown:boolean = false;
isShown = true;
(4)null类型:
let name:null = null;
(5)undefined类型:
let sex:undefined = undefined;
总结:默认情况下null和undefined是所有类型的子类型 === null和undefined可赋值给number类型的变量,严格模式下(strict),null只能赋值给void及本身,若想传入string | null | undefined可使用联合类型
1.4.2 复杂数据类型
(1)Array类型:
- 写法一:元素类型[]:表示由该类型的元素组成的一个数组
let list1:number[] = [1,2,3]; // 表示是number类型的数组
let list2:string[] = ['张三','李四']; //表示是string类型的数组
- 写法二:数组泛型:Array<元素类型>:<>中指定元素类型是什么,那么该数组只能定义该类型
let list3:Array<number> = [1,2,3]; //该数组只能写数字类型
let list4:Array<string> = ['小红','小明']; //该数组只能写string类型
(2)Map对象:
-
Map 对象保存键值对,并且能够记住键的原始插入顺序
-
任何值(对象或者原始值) 都可以作为一个键或一个值
-
Map 是 ES6 中引入的一种新的数据结构
-
创建Map:
let myMap = new Map(); eg: // 初始化 Map,可以以数组的格式来传入键值对: let myMap = new Map([ ["key1", "value1"], ["key2", "value2"] ]);
1.4.3 其他数据类型
(1)tuple类型:定义多个元素数量和类型的数组,其元素的类型无需相同
let x:[string, number]; // 第一个元素类型为string,第二个元素类型为number
x = ["你好", 12];
// 拓展1:访问已知索引的元素,返回正确的类型
console.log(x[0].substr(1)); // 访问x中的第一个元素,方法为substr说明元素是一个string类型
// 拓展2:访问越界的元素,会使用联合类型替代
x[3] = 'hello'; // 可以,string可赋值给string | number类型
console.log(x[5].toString()); // 可以,string和number都有toString方法
x[6] = true; // 错误,true是boolean类型不是string | number类型
(2)enum类型:枚举类型 可为一组数值赋予名字
- 写法一:元素编号默认是从0开始
enum Color {Yellow, Green, Blue}
let c:Color = Color.Blue; // 输出值为1,索引值,元素编号默认从0开始
- 写法二:可手动更改元素编号
enum Color {Yellow = 1, Green, Blue}
let c:Color = Color.Green; // 输出值是2,从1往后加
写法三:全部手动赋值
enum Color {Yellow = 1, Green = 2, Blue = 5}
let c:Color = Color.Green; // 输出值是2,手动赋值就是2
(3)any类型:应用场景:不清楚变量的类型,可能是动态的、用户输入、第三方代码库、dom、只知道部分数据类型
let inputValue:any = 4;
inputValue = 'isString';
inputValue = true;
// 获取DOM、修改DOM的style
var dom = document.getElementById('box'); // 能运行但会报错
var dom = document.getElementById('box'); // 能运行且不会报错
dom.style.color = 'green';
// 只知道部分数据类型,例如数组中包含不同类型的数据
let list:any[] = [1,false,'你好'];
list[1] = 100;
(4)never类型:表示永不存在的值,是任何类型的子类型,也可赋值给任何类型,没有类型是never的子类型、能被赋值给never类型、只有never本身可以赋值给never
应用场景:抛出异常、没有返回值的函数表达式或箭头函数表达式的返回值类型
// 返回never的函数必须存在无法达到的终点
function error(message:string):never{
throw new Error(message);
}
// 推断的返回值类型为never
function fail(){
return error('抛出错误')
}
// 返回never的函数必须存在无法到达的终点
function infiniteLoop():never{
while(true){
}
}
(5)void类型:表示没有任何类型,函数没有返回值,其返回值类型是void
// 函数没有返回值,返回值是void
function Warning():void{
console.log('warning!!!');
}
// 根据对应返回的数据
function Warning1():number{
return 123
}
// 声明一个void类型的变量,意义不大,只能将null或undefined进行赋值
let empty:void = undefined;
二、变量声明
2.1 命名规则
(1)变量名可包含数字和字母
(2)除下划线_和美元$符号外,不能包含其他特殊字符,包括空格
(3)不能数字开头
2.2 变量声明方式(4种)
(1)声明变量的类型及初始值:
var [变量名]:[类型] = 值;
var name:string = "张三";
(2)声明变量的值但无初始值(值为undefined):
var [变量名]:[类型];
var name:string;
(3)声明变量及初始值但未设置类型(类型可为任意类型):
var [变量名] = 值;
var name = "张三";
(4)声明变量为任意类型及初始值为undefined:
var [变量名];
var name;
2.3 类型断言(Type Assertion)
(1)作用:可用来手动指定一个值的类型,允许变量从一种类型更改为另一种类型
(2)语法格式:
<类型>值 或者 值 as 类型
var str = '1';
var str2:number = <number> <any> str
2.4类型推断
(1)作用:未确定类型时,可进行类型推断来推断类型
(2)注意:若未声明类型时,默认为any类型
(3)语法格式:
var num = 2; // 类型推断为number
console.log("num变量的值为"+num);
num = "12"; //编译错误
console.log(num); //num被定义为number类型
2.5变量作用域
(1)作用:指定了变量定义的位置
(2)类型:3种
-
全局作用域:全局变量定义在程序结构的外部,范围:可在代码中的任意位置进行使用
-
类作用域:又称为字段,范围:类变量声明在类中,处于类方法外;该变量可通过类的对象来访问。类变量也可是静态的,静态的变量可通过类名直接访问
-
局部作用域:局部变量,范围:代码块中进行使用(方法)
var global_num = 12 // 全局变量
class Numbers {
num_val = 13; // 实例变量
static sval = 10; // 静态变量storeNum():void {
var local_num = 14; // 局部变量
}
}
console.log("全局变量为: "+global_num)
console.log(Numbers.sval) // 静态变量
var obj = new Numbers();
console.log("实例变量: "+obj.num_val)
三、运算符(8种)
(1)类型:8种
3.1 算术运算符
运算符 | 描述 | 例子 | x 运算结果 | y 运算结果 |
---|---|---|---|---|
+ | 加法 | x=y+2 | 7 | 5 |
- | 减法 | x=y-2 | 3 | 5 |
* | 乘法 | x=y*2 | 10 | 5 |
/ | 除法 | x=y/2 | 2.5 | 5 |
% | 取模(余数) | x=y%2 | 1 | 5 |
++ | 自增 | x=++y | 6 | 6 |
x=y++ | 5 | 6 | ||
– | 自减 | x=–y | 4 | 4 |
x=y– | 5 | 4 |
3.2 逻辑运算符
运算符 | 描述 | 例子 |
---|---|---|
&& | and | (x < 10 && y > 1) 为 true |
|| | or | (x5 || y5) 为 false |
! | not | !(x==y) 为 true |
3.3 关系运算符
运算符 | 描述 | 比较 | 返回值 |
---|---|---|---|
== | 等于 | x==8 | false |
x==5 | true | ||
!= | 不等于 | x!=8 | true |
> | 大于 | x>8 | false |
< | 小于 | x<8 | true |
>= | 大于或等于 | x>=8 | false |
<= | 小于或等于 | x<=8 | true |
3.3 按位运算符
运算符 | 描述 | 例子 | 类似于 | 结果 | 十进制 |
---|---|---|---|---|---|
& | AND,按位与处理两个长度相同的二进制数,两个相应的二进位都为 1,该位的结果值才为 1,否则为 0。 | x = 5 & 1 | 0101 & 0001 | 0001 | 1 |
| | OR,按位或处理两个长度相同的二进制数,两个相应的二进位中只要有一个为 1,该位的结果值为 1。 | x = 5 | 1 | 0101 | 0001 | 0101 | 5 |
~ | 取反,取反是一元运算符,对一个二进制数的每一位执行逻辑反操作。使数字 1 成为 0,0 成为 1。 | x = ~ 5 | ~0101 | 1010 | -6 |
^ | 异或,按位异或运算,对等长二进制模式按位或二进制数的每一位执行逻辑异按位或操作。操作的结果是如果某位不同则该位为 1,否则该位为 0。 | x = 5 ^ 1 | 0101 ^ 0001 | 0100 | 4 |
<< | 左移,把 << 左边的运算数的各二进位全部左移若干位,由 << 右边的数指定移动的位数,高位丢弃,低位补 0。 | x = 5 << 1 | 0101 << 1 | 1010 | 10 |
>> | 右移,把 >> 左边的运算数的各二进位全部右移若干位,>> 右边的数指定移动的位数。 | x = 5 >> 1 | 0101 >> 1 | 0010 | 2 |
>>> | 无符号右移,与有符号右移位类似,除了左边一律使用0 补位。 | x = 2 >>> 1 | 0010 >>> 1 | 0001 | 1 |
3.4 赋值运算符
运算符 | 例子 | 实例 | x 值 |
---|---|---|---|
= (赋值) | x = y | x = y | x = 5 |
+= (先进行加运算后赋值) | x += y | x = x + y | x = 15 |
-= (先进行减运算后赋值) | x -= y | x = x - y | x = 5 |
*= (先进行乘运算后赋值) | x *= y | x = x * y | x = 50 |
/= (先进行除运算后赋值) | x /= y | x = x / y | x = 2 |
3.5 三元/条件运算符
Test ? expr1 : expr2
^: expr2:如果条件语句 Test 返回 false 则返回该值
var num:number = -2;
var result = num > 0 ? "大于 0" : "小于 0,或等 于 0" ;
console.log(result); // 输出结果:小于0,或等于0
3.6 类型运算符
- typeof运算符(是一元运算符,返回操作数的是数据类型)
3.7 其他运算符
3.7.1 负号运算符(-)
var x:number = 4;
var y = -x;
console.log("x 值为: ",x); // 输出结果 4
console.log("y 值为: ",y); // 输出结果 -4
3.7.2 字符串运算符(连接运算符 +)
var msg:string = "RUNOOB"+".COM";
console.log(msg);
四、条件语句(4种)
4.1 if语句
(1)使用:只有当指定条件为true
(2)语法:
if(boolean_expression){
# 在布尔表达式 boolean_expression 为 true 执行
}
eg:
var num:number = 5
if (num > 0) {
console.log("数字是正数")
}
4.2 if…else语句
(1)使用:一个 if 语句后可跟一个可选的 else 语句,else 语句在布尔表达式为 false 时执行。
(2)语法:
if(boolean_expression){
# 在布尔表达式 boolean_expression 为 true 执行
}else{
# 在布尔表达式 boolean_expression 为 false 执行
}
eg:
var num:number = 12;
if (num % 2==0) {
console.log("偶数");
} else {
console.log("奇数");
}
4.3 if…else if…else语句
(1)使用:执行多个判断条件时
(2)语法:
if(boolean_expression 1) {
# 在布尔表达式 boolean_expression 1 为 true 执行
} else if( boolean_expression 2) {
# 在布尔表达式 boolean_expression 2 为 true 执行
} else if( boolean_expression 3) {
# 在布尔表达式 boolean_expression 3 为 true 执行
} else {
# 布尔表达式的条件都为 false 时执行
}
eg:
var num:number = 2
if(num > 0) {
console.log(num+" 是正数")
} else if(num < 0) {
console.log(num+" 是负数")
} else {
console.log(num+" 不是正数也不是负数")
}
(3)注意:
- if后可有0个或1个else语句,必须在else…if后
- if后可有0个或多个else…if,这些语句必须在else之前
- 一旦执行了else…if内的代码,后面的else…if或else将不再执行
4.3 switch…case语句
(1)使用:一个变量存在多个值时,或这需要更确定的值时
(2)语法:
switch(expression){
case constant-expression :
statement(s);
break; /* 可选的 */
case constant-expression :
statement(s);
break; /* 可选的 */
/* 您可以有任意数量的 case 语句 */
default : /* 可选的 */
statement(s);
}
(3)注意:
- switch 语句中的 expression 是一个常量表达式,必须是一个整型或枚举类型。
- 在一个 switch 中可以有任意数量的 case 语句。每个 case 后跟一个要比较的值和一个冒号。
- case 的 constant-expression 必须与 switch 中的变量具有相同的数据类型,且必须是一个常量或字面量。
- 当被测试的变量等于 case 中的常量时,case 后跟的语句将被执行,直到遇到 break 语句为止。
- 当遇到 break 语句时,switch 终止,控制流将跳转到 switch 语句后的下一行。
- 不是每一个 case 都需要包含 break。如果 case 语句不包含 break,控制流将会 继续 后续的 case,直到遇到 break 为止。
- 一个 switch 语句可以有一个可选的 default case,出现在 switch 的结尾。default case 可用于在上面所有 case 都不为真时执行一个任务。default case 中的 break 语句不是必需的。
五、循环
5.1 for循环
(1)作用:用于多次执行一个语句序列,简化管理循环变量的代码
(2)语法:
for ( init; condition; increment ){
statement(s);
}
eg:
var num:number = 5;
var i:number;
var factorial = 1;
for(i = num;i>=1;i--) {
factorial *= i;
}
console.log(factorial)
5.2 for…in循环
(1)作用:用于一组值的集合或列表进行迭代输出
(2)语法:
for (var val in list) {
//语句
}
eg:
var j:any;
var n:any = "a b c"
for(j in n) {
console.log(n[j])
}
5.3 for…of循环(ES6中)
(1)作用:创建一个循环来迭代可迭代的对象(ES6中可替代for…in和forEach(),与之类似功能的还有forEach、every、some循环)
(2)语法:
let someArray = [1, "string", false];
for (let entry of someArray) {
console.log(entry); // 1, "string", false
}
eg:
let list = [4, 5, 6];
list.forEach((val, idx, array) => {
// val: 当前值
// idx:当前index
// array: Array
});
5.4 while循环
(1)作用:在给定条件为 true 时,重复执行语句或语句组
(2)语法:
while(condition){
statement(s);
}
eg:
var num:number = 5;
var factorial:number = 1;
while(num >=1) {
factorial = factorial * num;
num--;
}
console.log("5 的阶乘为:"+factorial);
5.5 do…while循环
(1)作用:在循环的尾部检查它的条件
(2)语法:
do{
statement(s);
}while( condition );
eg:var n:number = 10;
do {
console.log(n);
n--;
} while(n>=0);
5.6 无限循环(死循环)
(1)不会停止的循环
(2)语法:
for(;;) {
// 语句
}
eg:
for(;;) {
console.log("这段代码会不停的执行")
}
while(true) {
// 语句
}
eg:
while(true) {
console.log("这段代码会不停的执行")
}
六、特殊语句
6.1 break语句
(1)用法:2种
- 当break语句出现在一个循环内时,循环会立即终止,且会退出当前循环,并执行循环外的下一条语句
- 可用于终止switch语句中的一个case
(2)语法:
break;
eg:
var i:number = 1
while(i<=10) {
if (i % 5 == 0) {
console.log ("在 1~10 之间第一个被 5 整除的数为 : "+i)
break // 找到一个后退出循环
}
i++
} // 输出 5 然后程序执行结束
6.2 continue语句
(1)用法:非强制终止,跳过当前循环,开始执行循环内的下一次循环
- 对于 for 循环,continue 语句执行后自增语句仍然会执行。对于 while 和 do…while 循环,continue 语句重新执行条件判断语句。
(2)语法:
continue;
eg:
var num:number = 0
var count:number = 0;
for(num=0;num<=20;num++) {
if (num % 2==0) {
continue;
}
count++
}
console.log ("0 ~20 之间的奇数个数为: "+count) //输出10个偶数
七、函数
(1)定义:函数是一组一起执行一个任务的语句(函数的定义提供了函数的实际主体)
(2)组成:函数名称、返回类型、参数
(3)语法格式:
function function_name(){
// 执行代码
};
// 调用函数
function_name();
eg:
function test() {
// 函数定义
console.log("调用函数")
};
// 调用函数
test();
7.1 函数返回值
- 使用return语句后,函数会停止执行
function function_name():return_type {
// 语句
return value;
}
eg:
// 函数定义
function greet():string { // 返回一个字符串
return "Hello World";
}
function caller() {
var msg = greet(); // 调用 greet() 函数
console.log(msg);
}
// 调用函数
caller();
- 通常一个函数只有一个return语句
- 返回值的类型须臾函数定义的返回类型一直
7.2 带参函数
在调用函数时所传递的值,参数可在函数中使用,且可想函数发送多个参数,每个参数之间使用都好 , 分隔
语法格式:
function func_name( param1 [:datatype], param2 [:datatype]) {
}
eg:
function add(x: number, y: number): number {
return x + y;
}
console.log(add(1,2));
- param1、param2 为参数名。
- datatype 为参数类型。
7.3 可选参数和默认参数
- 定义了参数,则必须传入这些参数,除非将这些参数设置为可选,可选参数使用问号标识 ?
function buildName(firstName: string, lastName: string) {
return firstName + " " + lastName;
}
let result1 = buildName("Bob"); // 错误,缺少参数
let result2 = buildName("Bob", "Adams", "Sr."); // 错误,参数太多了
let result3 = buildName("Bob", "Adams"); // 正确
eg:
function buildName(firstName: string, lastName?: string) {
if (lastName)
return firstName + " " + lastName;
else
return firstName;
}
let result1 = buildName("Bob"); // 正确
// 错误,参数太多了
let result2 = buildName("Bob", "Adams", "Sr.");
let result3 = buildName("Bob", "Adams"); // 正确
7.4 默认参数
- 可以设置参数的默认值,这样在调用函数的时候,如果不传入该参数的值,则使用默认参数
function name(param1[:type],param2[:type]=default_value){}
eg:
function calculate_discount(price:number,rate:number = 0.50) {
var discount = price * rate;
console.log("计算结果: ",discount);
}
calculate_discount(1000);
calculate_discount(1000,0.30);
- 注意:参数不能同时设置为可选和默认
7.5 剩余参数
- 在不清楚需向函数传入多少个参数时,使用剩余参数来定义
function buildName(firstName: string, ...restOfName: string[]) {
return firstName + " " + restOfName.join(" ");
}
let employeeName = buildName("Joseph", "Samuel", "Lucas", "MacKinzie");
eg:
function addNumbers(...nums:number[]) {
var i;
var sum:number = 0;
for(i = 0;i<nums.length;i++) {
sum = sum + nums[i];
}
console.log("和为:",sum);
}
addNumbers(1,2,3);
addNumbers(10,10,10,10,10);
7.6 匿名函数
(1)定义:匿名函数即没有函数名的函数(给匿名函数赋值一个变量,即为函数表达式)
(2)语法格式:
var res = function( [arguments] ) { ... }
eg:
var msg = function() {
return "hello world";
}
console.log(msg());
(3)匿名函数的自调用:
(function () {
var x = "Hello!!";
console.log(x);
})();
7.7 构造函数
(1)语法格式:
var res = new Function ([arg1[, arg2[, ...argN]],] functionBody);
eg:
var myFunction = new Function("a", "b", "return a * b");
var x = myFunction(4, 3);
console.log(x);
-
arg1, arg2, … argN:参数列表
-
functionBody:一个含有包括函数定义的 JavaScript 语句的字符串
7.8 递归函数
(1)本质:在函数内调用函数本身
function factorial(number) {
if (number <= 0) { // 停止执行
return 1;
} else {
return (number * factorial(number - 1)); // 调用自身
}
};
console.log(factorial(6)); // 输出 720
7.9 箭头函数(Lambda函数)
(1)箭头函数表达式的语法比函数表达式更短
( [param1, parma2,…param n] )=>statement;
( [param1, parma2,…param n] )=> {
// 代码块
}
eg:
var foo = (x:number)=>10 + x;
console.log(foo(100)) //输出结果为 110
// 不指定函数的参数类型,通过函数内来推断参数类型:
var func = (x)=> {
if(typeof x=="number") {
console.log(x+" 是一个数字")
} else if(typeof x=="string") {
console.log(x+" 是一个字符串")
}
}
func(12);
func("Tom");
7.10 函数重载
(1)重载是方法名字相同,而参数不同,返回类型可以相同也可以不同
(2)每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表
(3)参数类型不同:
function disp(string):void;
function disp(number):void;
(4)参数数量不同:
function disp(n1:number):void;
function disp(x:number,y:number):void;
(5)参数类型顺序不同:
function disp(n1:number,s1:string):void;
function disp(s:string,n:number):void;
- 如果参数类型不同,则参数类型应设置为 any
- 参数数量不同你可以将不同的参数设置为可选
function disp(s1:string):void;
function disp(n1:number,s1:string):void;
function disp(x:any,y?:any):void {
console.log(x);
console.log(y);
}
disp("abc");
disp(1,"xyz");
八、联合类型
(1)以通过管道(|)将变量设置多种类型,赋值时可以根据设置的类型来赋值
(2)只能赋值指定的类型,如果赋值其它类型就会报错
(3)语法格式:
Type1|Type2|Type3;
eg:
var val:string|number;
val = 12;
console.log("数字为 "+ val);
val = "Runoob" ;
console.log("字符串为 " + val);
(4)联合类型数组:
var arr:number[]|string[];
var i:number;
arr = [1,2,4];
console.log("**数字数组**");
for(i = 0;i<arr.length;i++) {
console.log(arr[i]);
}
arr = ["Runoob","Google","Taobao"]
console.log("**字符串数组**");
for(i = 0;i<arr.length;i++) {
console.log(arr[i]);
}
九、接口
(1)定义:接口是一系列抽象方法的声明,是一些方法特征的集合,这些方法都应该是抽象的,需要由具体的类去实现,然后第三方就可以通过这组抽象方法调用,让具体的类执行具体的方法
(2)语法格式:
interface interface_name {}
eg:
interface IPerson {
firstName:string,
lastName:string,
sayHi: ()=>string
}
var customer:IPerson = {
firstName:"Tom",
lastName:"Hanks",
sayHi: ():string =>{return "Hi there"}
}
console.log("Customer 对象 ");
console.log(customer.firstName);
console.log(customer.lastName);
console.log(customer.sayHi());
var employee:IPerson = {
firstName:"Jim",
lastName:"Blakes",
sayHi: ():string =>{return "Hello!!!"}
}
console.log("Employee 对象 ")
console.log(employee.firstName);
console.log(employee.lastName);
9.1 联合类型和接口
interface RunOptions {
program:string;
commandline:string[]|string|(()=>string);
}
// commandline 是字符串
var options:RunOptions = {program:"test1",commandline:"Hello"};
console.log(options.commandline)
// commandline 是字符串数组
options = {program:"test1",commandline:["Hello","World"]};
console.log(options.commandline[0]);
console.log(options.commandline[1]);
// commandline 是一个函数表达式
options = {program:"test1",commandline:()=>{return "**Hello World**";}};
var fn:any = options.commandline;
console.log(fn());
9.2 接口和数组
interface namelist {
[index:number]:string
}
// 类型一致,正确
var list2:namelist = ["Google","Runoob","Taobao"]
// 错误元素 1 不是 string 类型
// var list2:namelist = ["Runoob",1,"Taobao"]
9.3 接口继承
- 接口继承就是说接口可以通过其他接口来扩展自己
- Typescript 允许接口继承多个接口
- 继承使用关键字 extends ,继承的各个接口使用逗号 , 分隔
(1)单接口继承语法格式:
Child_interface_name extends super_interface_name;
eg :
interface Person {
age:number
}
interface Musician extends Person {
instrument:string
}
var drummer = <Musician>{};
drummer.age = 27
drummer.instrument = "Drums"
console.log("年龄: "+drummer.age)
console.log("喜欢的乐器: "+drummer.instrument)
(2)多接口继承语法格式:
Child_interface_name extends super_interface1_name, super_interface2_name,…,super_interfaceN_name
eg:
interface IParent1 {
v1:number
}
interface IParent2 {
v2:number
}
interface Child extends IParent1, IParent2 { }
var Iobj:Child = { v1:12, v2:23}
console.log("value 1: "+Iobj.v1+" value 2: "+Iobj.v2)
十、类
(1)TypeScript 是面向对象的 JavaScript;类描述了所创建的对象共同的属性和方法; TypeScript 支持面向对象的所有特性,比如 类、接口等。
(2)语法格式:
class class_name {
// 类作用域
}
eg:
class Person {
}
定义类的关键字为 class,后面紧跟类名,类可以包含以下几个模块(类的数据成员):
- 字段 − 字段是类里面声明的变量。字段表示对象的有关数据。
- 构造函数 − 类实例化时调用,可以为类的对象分配内存。
- 方法 − 方法为对象要执行的操作。
10.1 创建类的数据成员
以下实例我们声明了类 Car,包含字段为 engine,构造函数在类实例化后初始化字段 engine。
this 关键字表示当前类实例化的对象。注意构造函数的参数名与字段名相同,this.engine 表示类的字段。
此外我们也在类中定义了一个方法 disp()。
class Car {
// 字段
engine:string;
// 构造函数
constructor(engine:string) {
this.engine = engine
}
// 方法
disp():void {
console.log("发动机为 : "+this.engine)
}
}
10.2 创建实例化对象
var object_name = new class_name([ arguments ]);
eg:类实例化时会调用构造函数
var obj = new Car("Engine 1");
eg:类中的字段属性和方法可以使用.号来访问
// 访问属性
obj.field_name
// 访问方法
obj.function_name()
eg:完整实例
class Car {
// 字段
engine:string;
// 构造函数
constructor(engine:string) {
this.engine = engine
}
// 方法
disp():void {
console.log("函数中显示发动机型号 : "+this.engine)
}
}
// 创建一个对象
var obj = new Car("XXSY1")
// 访问字段
console.log("读取发动机型号 : "+obj.engine)
// 访问方法
obj.disp()
10.3 类的继承
(1)定义:TypeScript 支持继承类,即我们可以在创建类的时候继承一个已存在的类,这个已存在的类称为父类,继承它的类称为子类。类继承使用关键字 extends,子类除了不能继承父类的私有成员(方法和属性)和构造函数,其他的都可以继承。TypeScript 一次只能继承一个类,不支持继承多个类,但 TypeScript 支持多重继承(A 继承 B,B 继承 C)
(2)语法格式:
class child_class_name extends parent_class_name;
eg:实例中创建了Shape类,Circle类继承了Shape类,Circle类可直接使用Area属性
Area:number
constructor(a:number) {
this.Area = a
}
}
class Circle extends Shape {
disp():void {
console.log("圆的面积: "+this.Area)
}
}
var obj = new Circle(223);
obj.disp()
需要注意的是子类只能继承一个父类,TypeScript 不支持继承多个类,但支持多重继承,如下实例:
TypeScript
class Root {
str:string;
}
class Child extends Root {}
class Leaf extends Child {} // 多重继承,继承了 Child 和 Root 类
var obj = new Leaf();
obj.str ="hello"
console.log(obj.str)
10.4 继承类的方法重写
(1)定义:类继承后,子类可以对父类的方法重新定义,这个过程称之为方法的重写。其中 super 关键字是对父类的直接引用,该关键字可以引用父类的属性和方法。
class PrinterClass {
doPrint():void {
console.log("父类的 doPrint() 方法。")
}
}
class StringPrinter extends PrinterClass {
doPrint():void {
super.doPrint() // 调用父类的函数
console.log("子类的 doPrint()方法。")
}
}
10.5 static关键字
(1)static 关键字用于定义类的数据成员(属性和方法)为静态的,静态成员可以直接通过类名调用
class StaticMem {
static num:number;
static disp():void {
console.log("num 值为 "+ StaticMem.num)
}
}
StaticMem.num = 12 // 初始化静态变量
StaticMem.disp() // 调用静态方法
10.6 instanceof运算符
(1)instanceof 运算符用于判断对象是否是指定的类型,如果是返回 true,否则返回 false
class Person{ }
var obj = new Person()
var isPerson = obj instanceof Person;
console.log("obj 对象是 Person 类实例化来的吗? " + isPerson);
10.7 访问控制修饰符
(1)TypeScript 中,可以使用访问控制符来保护对类、变量、方法和构造方法的访问。TypeScript 支持 3 种不同的访问权限。
- public(默认) : 公有,可以在任何地方被访问。
- protected : 受保护,可以被其自身以及其子类访问。
- private : 私有,只能被其定义所在的类访问。
class Encapsulate {
str1:string = "hello"
private str2:string = "world"
}
var obj = new Encapsulate()
console.log(obj.str1) // 可访问
console.log(obj.str2) // 编译错误, str2 是私有的
10.8 类和接口
(1)定义:类可以实现接口,使用关键字 implements,并将 interest 字段作为类的属性使用
interface ILoan {
interest:number
}
class AgriLoan implements ILoan {
interest:number
rebate:number
constructor(interest:number,rebate:number) {
this.interest = interest
this.rebate = rebate
}
}
var obj = new AgriLoan(10,1)
console.log("利润为 : "+obj.interest+",抽成为 : "+obj.rebate )
十一、对象
(1)定义:对象是包含一组键值对的实例。 值可以是标量、函数、数组、对象等
var object_name = {
key1: "value1", // 标量
key2: "value",
key3: function() {
// 函数
},
key4:["content1", "content2"] //集合
}
eg:
var sites = {
site1:"Runoob",
site2:"Google"
};
// 访问对象的值
console.log(sites.site1)
console.log(sites.site2)
11.1类型模板
var sites = {
site1:"Runoob",
site2:"Google"
};
// 在对象中添加方法
sites.sayHello = function(){ return "hello";}
eg:
var sites = {
site1: "Runoob",
site2: "Google",
sayHello: function () { } // 类型模板
};
sites.sayHello = function () {
console.log("hello " + sites.site1);
};
sites.sayHello();
// 对象作为参数传递给函数
var sites = {
site1:"Runoob",
site2:"Google",
};
var invokesites = function(obj: { site1:string, site2 :string }) {
console.log("site1 :"+obj.site1)
console.log("site2 :"+obj.site2)
}
invokesites(sites)
11.2 鸭子类型(Duck Typing)
(1)定义:鸭子类型(英语:duck typing)是动态类型的一种风格,是多态(polymorphism)的一种形式。在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由"当前方法和属性的集合"决定。在鸭子类型中,关注点在于对象的行为能做什么,而不是关注对象所属的类型
interface IPoint {
x:number
y:number
}
function addPoints(p1:IPoint,p2:IPoint):IPoint {
var x = p1.x + p2.x
var y = p1.y + p2.y
return {x:x,y:y}
}
// 正确
var newPoint = addPoints({x:3,y:4},{x:5,y:1})
// 错误
var newPoint2 = addPoints({x:1},{x:4,y:3})
十二、命名空间
(1)作用:解决重名问题
(2)语法格式:
namespace SomeNameSpaceName {
export interface ISomeInterfaceName { }
export class SomeClassName { }
}
以上定义了一个命名空间 SomeNameSpaceName,如果我们需要在外部可以调用 SomeNameSpaceName 中的类和接口,则需要在类和接口添加 export 关键字。
要在另外一个命名空间调用语法格式为:
SomeNameSpaceName.SomeClassName;
如果一个命名空间在一个单独的 TypeScript 文件中,则应使用三斜杠 /// 引用它,语法格式如下:
/// <reference path = "SomeFileName.ts" />
以下实例演示了命名空间的使用,定义在不同文件中:
IShape.ts 文件代码:
namespace Drawing {
export interface IShape {
draw();
}
}
Circle.ts 文件代码:
/// <reference path = "IShape.ts" />
namespace Drawing {
export class Circle implements IShape {
public draw() {
console.log("Circle is drawn");
}
}
}
Triangle.ts 文件代码:
/// <reference path = "IShape.ts" />
namespace Drawing {
export class Triangle implements IShape {
public draw() {
console.log("Triangle is drawn");
}
}
}
TestShape.ts 文件代码:
/// <reference path = "IShape.ts" />
/// <reference path = "Circle.ts" />
/// <reference path = "Triangle.ts" />
function drawAllShapes(shape:Drawing.IShape) {
shape.draw();
}
drawAllShapes(new Drawing.Circle());
drawAllShapes(new Drawing.Triangle());
12.1 嵌套命名空间
(1)命名空间支持嵌套,即你可以将命名空间定义在另外一个命名空间里头。
namespace namespace_name1 {
export namespace namespace_name2 {
export class class_name { }
}
}
eg:
成员的访问使用点号 . 来实现,如下实例:
Invoice.ts 文件代码:
namespace Runoob {
export namespace invoiceApp {
export class Invoice {
public calculateDiscount(price: number) {
return price * .40;
}
}
}
}
InvoiceTest.ts 文件代码:
/// <reference path = "Invoice.ts" />
var invoice = new Runoob.invoiceApp.Invoice();
console.log(invoice.calculateDiscount(500));
十三、模块
(1)TypeScript 模块的设计理念是可以更换的组织代码。模块是在其自身的作用域里执行,并不是在全局作用域,这意味着定义在模块里面的变量、函数和类等在模块外部是不可见的,除非明确地使用 export 导出它们。类似地,我们必须通过 import 导入其他模块导出的变量、函数、类等。两个模块之间的关系是通过在文件级别上使用 import 和 export 建立的。模块使用模块加载器去导入其它的模块。 在运行时,模块加载器的作用是在执行此模块代码前去查找并执行这个模块的所有依赖。 大家最熟知的JavaScript模块加载器是服务于 Node.js 的 CommonJS 和服务于 Web 应用的 Require.js。此外还有有 SystemJs 和 Webpack。
模块导出使用关键字 export 关键字,语法格式如下:
// 文件名 : SomeInterface.ts
export interface SomeInterface {
// 代码部分
}
要在另外一个文件使用该模块就需要使用 import 关键字来导入:
import someInterfaceRef = require("./SomeInterface");
IShape.ts 文件代码:
/// <reference path = "IShape.ts" />
export interface IShape {
draw();
}
Circle.ts 文件代码:
import shape = require("./IShape");
export class Circle implements shape.IShape {
public draw() {
console.log("Cirlce is drawn (external module)");
}
}
Triangle.ts 文件代码:
import shape = require("./IShape");
export class Triangle implements shape.IShape {
public draw() {
console.log("Triangle is drawn (external module)");
}
}
TestShape.ts 文件代码:
import shape = require("./IShape");
import circle = require("./Circle");
import triangle = require("./Triangle");
function drawAllShapes(shapeToDraw: shape.IShape) {
shapeToDraw.draw();
}
drawAllShapes(new circle.Circle());
drawAllShapes(new triangle.Triangle());
十四、声明文件
(1)TypeScript 作为 JavaScript 的超集,在开发过程中不可避免要引用其他第三方的 JavaScript 的库。虽然通过直接引用可以调用库的类和方法,但是却无法使用TypeScript 诸如类型检查等特性功能。为了解决这个问题,需要将这些库里的函数和方法体去掉后只保留导出类型声明,而产生了一个描述 JavaScript 库和模块信息的声明文件。通过引用这个声明文件,就可以借用 TypeScript 的各种特性来使用库文件了。
(2)文件后缀:d.ts
(3)语法格式:
declare module Module_Name {
}
TypeScript 引入声明文件语法格式:
/// <reference path = " runoob.d.ts" />
CalcThirdPartyJsLib.js 文件代码:
var Runoob;
(function(Runoob) {
var Calc = (function () {
function Calc() {
}
})
Calc.prototype.doSum = function (limit) {
var sum = 0;
for (var i = 0; i <= limit; i++) {
sum = sum + i;
}
return sum;
}
Runoob.Calc = Calc;
return Calc;
})(Runoob || (Runoob = {}));
var test = new Runoob.Calc();
如果我们想在 TypeScript 中引用上面的代码,则需要设置声明文件 Calc.d.ts,代码如下:
Calc.d.ts 文件代码:
declare module Runoob {
export class Calc {
doSum(limit:number) : number;
}
}
声明文件不包含实现,它只是类型声明,把声明文件加入到 TypeScript 中:
CalcTest.ts 文件代码:
/// <reference path = "Calc.d.ts" />
var obj = new Runoob.Calc();
// obj.doSum("Hello"); // 编译错误
console.log(obj.doSum(10));
注明:大部分来源于菜鸟教程,仅供记录个人学习使用不做商用