介绍TypeScript
首先在学习理论知识前,谈论一下,TypeScript与JavaScript有什么区别呢?为什么要使用它,能够解决项目中的哪些问题?
1.是什么?为什么?
始于JavaScript归于JavaScript:TypeScript是JavaScript的超类,并且支持es2015中的特性,可以被编译为纯的JavaScript。提供了一套强类型语言的规范,因此伴随这强类型语言带来的优势有:1.静态类型检测,避免了不必要的错误 2.IDE智能提示,避免了翻api的麻烦,鼠标移到方法上便可了解数据类型等等3.代码重构,能快速定位变量所在的地方4.可读性,类型一目了然。
总结一下:1.模块管理更佳 2.类型检查更严格3.使我的开发严谨而自由。
常用知识点:基础类型,常量声明
1.基础类型
TypeScript支持与JavaScript几乎相同的数据类型,此外还提供了实用的枚举类型方便我们使用。
布尔值:boolean
范围:Js中的true,false
例:Let a:boolean = false;
数字:number
范围:Js中的所有数字
例:Let a:number = 6;
字符串:string
范围:可以使用””,’’,``(模版字符串语法)表示字符串
例:let a:string=`这是模版字符串`;
数组(type表示元素类型)
第一种表示方式:type[]
例子:let a:string[] = [‘a’,’b’];
第二种表示方式 Arrary
例子:let a:Array
元组
定义:表示一个已知元素数量和类型的数组,各数组类型不一定相同
例子:let a:[string,number];
a = [‘a’,2]; ------OK;
a = [2,’a’]; ------error;
当访问一个越界的元素,会使用联合类型(元组内定义过的类型)代替
例子:
a[3] = ‘a’; -------ok
a[3] = true; -------error
枚举:enum
定义:是对JS的一个补充,可以为一组数值赋予友好的名字。
例子:定义枚举: enmu color{red , blue , green};
访问枚举1.:let c:color = color.blue; --------c=2 ;默认从0开始
定义枚举:enmu color{red=3 , blue , green};,这样将按顺序,从3递增
访问枚举2.:let c:string= color[4]; --------c=’blue’ ;
任意类型:any
定义:当不清楚类型的变量指定的类型
空类型:void
定义:与any想反,表示没有任意类型。通常用于定义函数没有返回值。
Null和Undefined
定义:与js中相似,默认情况下null和undefined是所有类型的子类型。 就是说你可以把 null和undefined赋值给number类型的变量。
Never
定义:表示永不存在的值的类型
类型断言
定义:相当于其他语言的类型转换,运行时对数据没有任何影响,只是在编译时,进行相对应的检查。
两种用法:
例1:尖括号语法
let someValue: any = "this is a string";
let strLength: number = (
例1:as语法(推荐使用,在jsx语法中,语法是被允许的)
let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;
2.变量声明
定义:let和canst是es2015新的变量声明方式,当然在TypeScript中也是支持的。
2.1Var声明
2.1.1作用域规则:
var声明可以在包含它的函数,模块,命名空间或全局作用域内部任何位置被访问,被称为函数作用域。会引发一些错误,其中之一就是多次声明同一个变量不会报错。
2.1.2变量的怪异之处:
下面的代码会返回什么:
for (var i = 0; i < 10; i++) {
setTimeout(function() { console.log(i); }, 100 * i);
}
结果:
10
10
10
10
10
10
10
10
10
10
很多JavaScript程序员对这种行为已经很熟悉了,但如果你很不解,你并不是一个人。 大多数人期望输出结果是这样:
0
1
2
3
4
5
6
7
8
9
还记得我们上面提到的捕获变量吗?
我们传给setTimeout的每一个函数表达式实际上都引用了相同作用域里的同一个i。
让我们花点时间思考一下这是为什么。 setTimeout在若干毫秒后执行一个函数,并且是在for循环结束后。for循环结束后,i的值为10。 所以当函数被调用的时候,它会打印出 10!
一个通常的解决方法是使用立即执行的函数表达式(IIFE)来捕获每次迭代时i的值:
for (var i = 0; i < 10; i++) {
(function(i) {
setTimeout(function() { console.log(i); }, 100 * i);
})(i);
}
这种奇怪的形式我们已经司空见惯了。 参数 i会覆盖for循环里的i,但是因为我们起了同样的名字,所以我们不用怎么改for循环体里的代码。
2.2Let声明
定义:语法与var相同,语义上不同。
例子:let name=”hyb”;
2.2.1块作用域
以块为作用域,块之外是访问不到变量的,这里我们定义了2个变量a和b。 a的作用域是f函数体内,而b的作用域是if语句块里。
例子:function f(input: boolean) {
let a = 100;
if (input) {
// Still okay to reference 'a'
let b = a + 1;
return b;
}
// Error: 'b' doesn't exist here
return b;
}
并且:我们不能在let定义变量前访问它
例子:
a++; // illegal to use 'a' before it's declared;
let a;
2.2.2重定义及屏蔽
let定义的变量不允许在同一个块级作用域中被重新定义。
例:
let x = 10;
let x = 20; // 错误,不能在1个作用域里多次声明`x`。
function f(x) {
let x = 100; // error: interferes with parameter declaration
}
function g() {
let x = 100;
var x = 100;
// error: can't have both declarations of 'x'
}
在一个嵌套作用域里(即不同块作用域内)引入一个新名字的行为称做屏蔽。 它是一把双刃剑,它可能会不小心地引入新问题,同时也可能会解决一些错误。
function sumMatrix(matrix: number[][]) {
let sum = 0;
for (let i = 0; i < matrix.length; i++) {
var currentRow = matrix[i];
for (let i = 0; i < currentRow.length; i++) {
sum += currentRow[i];
}
}
return sum;
} ---------------------内层循环的i可以屏蔽掉外层循环的i。
因此,上面var声明变量遇到的问题。let可以轻松的解决。
for (let i = 0; i < 10 ; i++) {
setTimeout(function() {console.log(i); }, 100 * i);
}
会输出与预料一致的结果:
0
1
2
3
4
5
6
7
8
9
2.3const声明
定义:与let声明类似,唯一的区别便是,const声明的变量不能被重新赋值。
2.4解构
2.4.1解构数组
解构赋值:
let input = [1,2];
let [frist,second] = input; --------frist = 1,second= 2;
作用与函数
function f([frist,second]:[number,number]){
console.log(frist);
console.log(second);
}
在数组里使用...语法创建剩余变量:
let [frist,...prop] = [1,2,3,4]; -------------frist = 1, prop = [2,3,4]
2.4.2对象解构
用法与数组解构类似:
let o = { a: "foo", b: 12, c: "bar" };
let { a, b } = o; ----------a = “foo”,b = 12
let { a, ...passthrough } = o; ------------a = “foo”,passthrough = {b:12,c:”bar”}
2.5展开
展开操作符正与解构相反。 它允许你将一个数组展开为另一个数组,或将一个对象展开为另一个对象。
例如:
let first = [1, 2];
let second = [3, 4];
let bothPlus = [0, ...first, ...second, 5]; -------------bothplus = [0,1,2,3,4,5].
当然你还可以展开对象:
let defaults = { food: "spicy", price: "$$", ambiance: "noisy" };
let search = { ...defaults, food: "rich" }; -----search = { food: "rich", price: "$$", ambiance: "noisy" }也就是说后面定义的属性会覆盖前面的属性。
**注意:当展开的对象中有方法时,展开后会丢失。
typescript还有几个常要基于es6的知识点,接口、类、函数、泛型,请看下一篇文章