一、TypeScript的特点
1.支持ES6规范
2.强大的IDE支持(集成开发环境)
-
允许为变量指定类型,减少你在开发阶段犯错误的几率。
-
语法提示,在IDE编写代码时,它会根据你所处的上下文把你能用的类,变量,方法,关键字给你提示出来。
-
重构,方便的修改变量,方法,文件的名字,当你修改的时候IDE会帮你把你用到过这些变量,方法的地方给修改掉。
3.Angular2的开发语言。
二、搭建TypeScipt的开发环境
1. 我们需要compiler(编译器)。
我们需要把 .ts 结尾的TypeScript文件给编译成 .js 结尾的JavsScript文件,因为现在有些浏览器是不支持ES6语法的,没办法直接让程序跑起来,所以我们需要编译成支持ES5的JavaScript语法。
TypeScript
3. 搭建本地开发环境
-
npm install typescript -g 全局安装
-
tsc --version 查看版本
-
./demo/hello.ts
-
tsc ./demo/hello.ts 会在它的同级目录生成一个hello.js文件
-
每次都这样的操作有点麻烦,我们开始使用IDE,它可以帮我做这些事情
创建项目目录打开CMDtsc --init 会生成tsconfig.json配置文件
{
"compilerOptions": {
"target": "es5",//翻译出来的语法
"module": "commonjs",//使用commonjs模块
"outDir": "./js/",//翻译出来的文件存放在./js文件夹中
"rootDir": "./tscript/",//需要翻译的文件放在./tscript文件夹中
"esModuleInterop": true
// esModuleInterop取决于设置的内容module。
// 如果有"module": "commonjs",则只需启用"esModuleInterop": true。
// 如果您有"module": "es2015"或者"module": "esnext",
//您还必须启用"allowSyntheticDefaultImports": true以便导入CommonJS模块(如React)作为默认值。
}
}
我们采用以上配置;
我们今天用Visual Studio Code来做示范打开创建好的项目文件夹,webstorm上的话会有提示插件更加方便。
新建tscript、js文件夹,分别用作存放typescript、javascript文件,在tscript目录中新建test.ts文件。
打开>菜单>终端>运行任务>
点击运行后,只要我们修改ts文件的代码且保存后会自动翻译
这就配置好了,接下来就可以正常开发了。
三、学习字符串
1、多行字符串
JS中我们声明变量是不可以换行的
var str = 'aaa
bbb
ccc'
/*上面这样的写法是会报错的,我们通常用下面的写法*/
var str = 'aaa'+
'bbb'+
'ccc';
TS中有多行字符串的写法用`` 来包裹
var str = `aaa
bbb
ccc`
//在这个里面你是可以任意换行的
//翻译成JS是这样的
var str = 'aaa\nbbb\nccc'
2、字符串模板
var myName = 'huoqingchi'
var getName = function () {
return 'huoqingchi';
}
console.log(`hello ${myName}`);//可以直接写表达式
console.log(`hello ${getName()}`);//也可以直接调用方法
//切记能这样做的原因是因为它们写在了``当中。
接下来我们见识下字符串模板的威力,用字符串拼接一段HTML
var myName = 'huoqingchi';
console.log(`<div>
<h1>你们好我是${myName}</h1>
<h1>${getName()}</h1>
</div>`);//可读性和书写实在是太好了。
3、自动拆分字符串
当你在用一个字符串模板去调用一个方法的时候这个字符串模板里面表达式的值会自动赋给被调用方法中的参数。
function test(template,name,age) {
console.log(template)
console.log(name)
console.log(age)
};
var myName = 'huoqingchi';
var getAge = function(){
return 18;
}
//如果你想使用字符串拆分的特性就不能直接圆括号调用test方法,需要用``。
//第一个参数是你的字符串模板。
//第二个参数就是你出现的第一个表达式的值。
//第三个参数就是你出现的第二个表达式的值。
test`hello ${myName},${getAge()}`
输出结果:
["hello ",",",""]
huoqingchi
18
四、参数的新特性
1、参数类型
在参数的名称后面我们可以使用冒号来指定参数的类型
因为我已经给str这个变量指定了string类型,所以我再给它赋值一个数值类型时会报错,这种情况只会出现在我们编写.ts文件时,当它给我们翻译成.js文件的时候还是会被赋值数值型的。
可是上面代码我明明没有给它指定类型了,为什么还是报错呢?
这是因为TypeScript有一个类型推断机制,如果你一次给这个变量存储的是字符串值,它会规定你这个变量只能存储字符串值。
如果想让一个变量又是字符串又是数值型;
我们可以给这个变量赋值一个any类型,它代表这个变量可以存储任何类型的值;
除了string和any类型我们还有
1、number //数值
2、boolean //true||false
3、void //用来声明方法的返回值的void代表这个函数不需要返回值,你也可以给这个方法设置返回规定的类性。除了给方法设置类性外,我们也可以给方法的参数设置类型,规定必须传入的参数。
4、自定义类型:
class Person {
name:string;
age:number;
}
var zhangsan :Person = new Person();
zhangsan.name = 'zhangsan'
zhangsan.age = 18;
//当你声明好Person类型后去调用会有语法提示你它当前有那些属性且他们的类性是什么。
如果你声明了一个变量,再声明一个同名函数会报错,
2、默认参数
这个时候我们可以给第三个形参设置一个默认值:
切记,需要设置默认参数的形参从后面依次排列,因为传入的参数是从第一个开始匹配的
3、可选参数
在方法的参数声明后面用? 来标明此参数为可选参数
这个时候运行会输出:
使用可选参数要注意的有两点:
1.可选参数没传的时候怎么处理,b参数没有传入,但是如果我在函数体里面直接去调它的话会报错;
例子:console.log(b.lenght) //这种错误非常常见undefined不能打点
2.可选参数是不可以声明在必选参数的前面;
五、函数新特性
1、Rest and Spread 操作符
1.1声明可以传入任意参数的方法(主要)
function func1(...args) {//这个...就是Rest and Spread 操作符
//用...声明的args参数可以传入任意数量的参数
args.forEach(function (arg) {
console.log(arg)
})//args就是一个数组,它内部用的是arguments,可以去观察翻译后的.js文件。
};
func1(1,2,3);
func1(4,5,6,7,8);
输出结果:
1.2 把任意长度的数组一个固定数量的方法的调用
function func1(a,b,c) {
console.log(a);//第一次传过来的是1,2没有第三个参数所以c是undefined
console.log(b);//第二次传过来的是5,4,2,34,2但是我们只有a,b,c三个形参接受,所以只会拿取前三个。
console.log(c);
};
var args = [1,2];
func1(...args);//这样的操作会把args数组里面的每一项给出来,当做实参传过去。
var args2 = [5,4,2,34,2];
func1(...args2);//因为TypeScript还不支持这种语法所以会报错,但是编译好的js文件可正常运行。
运行编译后的js文件输出结果:
2、generator函数
它可以控制函数的执行过程,手工暂停和恢复代码执行。
function* get() {//在function和函数名中间加*就是generator函数
console.log("start");
yield;//yield会将函数打断停留不继续往下执行
console.log("finish")
}
var func1 = get();//如果你直接去调用get函数是没用的,需要将它赋给一个变量。
func1.next();//通过调用.next()可以让函数执行。//输出start;
func1.next();//输出finish,//每次调用next会让函数执行且停留在下一个yield。
因为这个语法TypeScript暂时还不支持,它是es6规范的一部分,所以我们用到了babel翻译。
function *get() {
while (true) {//这个循环没有一直执行,只有下面price>limit为true的时候才会执行
yield Math.random()*100;
}
}
var priceG = get();//拿到get的执行权
var limit = 15;//最低15
var price = 100;//起始100
while (price>limit) {//如果低于15就停。
price = priceG.next().value;//通过.value得到get函数中yield返回的随机数且赋值给price
console.log(`${price}`)//输出yield返回的值
}
console.log(`${price}`);//如果拿到了小于15的数就会最后弹出
输出结果:
3、析构表达式
通过表达式将对象或数组拆解成任意数量的变量。
3.1 Object
function get() {
return {
xing:'huo',
age:18
}
}
var {xing,age} = get();
//{}中的变量名要跟你函数返回对象中的属性名相同
//如果想改名字:{xingshi:xing,age}
//console.log(xingshi);//'huo'
console.log(xing);//'huo'
console.log(age);//18
function get() {
return {
xing:'huo',
yifu:{//如果你返回的又是一个对象
kuzi:400,
shangyi:200
}
}
}
//那么我们可以再把里面的属性给析构
var {xing,yifu:{kuzi}} = get();
console.log(xing);//'huo'
console.log(kuzi);//400
3.2 Array
var arr1 = [1,2,3,4];
var [number1,number2] = arr1;
console.log(number1)//1
console.log(number2)//2
//如果要拿3和4
var [, , number1, number2] = arr1;
//站位,但是我不拿出来。
console.log(number1)//3
console.log(number2)//4
//如果要拿1和4
var [number1, , , number2] = arr1;
console.log(number1)//1
console.log(number2)//4
3.2 析构表达式和Rest操作符共用
var arr1 = [1,2,3,4];
var [number1,number2,...shengyu] = arr1;
console.log(number1)//1
console.log(number2)//2
console.log(shengyu)//[3,4]
var arr1 = [1,2,3,4];
function test([number1, number2, ...shengyu]) {
console.log(number1)//1
console.log(number2)//2
console.log(shengyu)//[3,4]
}
test(arr1);//类型“number[]”的参数不能赋给类型“[any, any, ...any[]]”的参数,但不影响我们使用。
六、表达式与循环
1、箭头表达式
用来声明匿名函数,消除传统匿名函数的this指向问题。
var sum = (arg1,arg2) => arg1+arg2; 这就是最简单的一行箭头表达式。如果返回值只有一行的话可以省略{}也不需要写return方法。如果是多行的话是需要写{}的。
var sum = () => {} 如果没有参数的话是这样的写法。
var sum = arg => {return arg} 如果只有一个参数的话圆括号都可以省略。
例子:
var myArray = [1,2,3,4,5,6];
console.log(myArray.filter(value => value%2 == 0))
//filter()是过虑的意思,()里面放的是表达式,如果取余2==0的话就返回,会得到[2,4,6]。
箭头表达式最大的好处this指向:
function get(name:string) {
this.name = name;
// setInterval(function () {
// console.log("name is"+this.name);
// //什么都得不到因为this指向的是window
// }, 1000);
setInterval(() => {
console.log("name is " + this.name);
//跟想得到的是一样的,因为this是它所处的上下文
}, 1000);
}
var stock = new get("huo");
2、循环
1、forEach
2、for...in...
3、for...of...
七、面向对象特性
1、类(class)
类是TypeScript的核心,使用TypeScript开发时,大部分代码都是写在类里面的。
这里会介绍类的定义,构造函数,以及类的继承。
class People {//TypeScript声明类的方法
name;//属性
getName(){//方法
console.log("huoqingchi");
}
//类拥有属性和方法
}
var p1 = new People();//我们通过new实例化了这个类,且赋值给了p1
p1.name = "rope";
p1.getName();
//同样一个类我们可以new出多个实例,且这些实例都拥有相同的属性和方法,但是状态不同。
var p2 = new People();//我们可以在实例化一个类,且赋值给了p2
p2.name = "scarf";
p2.getName();
访问控制符
管理类的属性和方法可以在哪里调用,一共有三个,且带声明效果。
1、public
class People {
public name;
public getName(){
console.log("huoqingchi");
}
//public的属性和方法都是可以在类的内部||类的外部访问的,它也是默认的,不写也可以。
}
2、private
3、protected
类的构造函数
class People {
constructor(){//类的构造函数就是它,一个特殊的方法。
//这个方法会在这个类实例化的时候被执行。
console.log("hhh")
}
}
var p1 = new People();//hhh
用处:实例化一个人的时候必须为他指定一个名字等等。。
//第一种写法
class People {
name;//声明了一个name属性
constructor(name:string){//这里接受实例化传来的值且设置参数类型
this.name = name;//这里会访问上面声明的name属性且给他传入我们接收到的值
};
getName(){
console.log(this.name);
}
}
var p1 = new People("rope");//在这里实例化的时候给constructor传入一个值
p1.getName();//rope
//第二种写法
class People {
constructor(public name:string){//这里接受实例化传来的值且设置参数类型
//这个写法会被People类创建一个name属性且把传入的值赋给它。
//构造函数上需要明确的声明访问控制符
};
getName(){
//如果构造函数中name没有声明访问控制符,People类里面也没有name属性。
console.log(this.name);//所以这里是得不到的。
}
}
var p1 = new People("rope");//在这里实例化的时候给constructor传入一个值
p1.getName();//rope
类的继承
1、extends
通过extends关键字可以实现继承
这个时候Student实例化的p1身上也拥有了People的属性和方法。
在Student类中的属性和方法People的实例是没有的。
2、super
第一个用法:调用父类的构造函数
class People {
constructor(public name:string){
//这里是被下面的super调用了。
//这个写法会被People类创建一个name属性且把传入的值赋给它。
console.log("People")
};
getName(){
console.log(this.name);
}
}
class Student extends People {
constructor(name: string, public code:string){//实例化一个学生必须有名字和学号
//这个写法会被Student类创建一个code属性且把传入的值赋给它。
super(name);//通过super可以调用父类(People)的构造函数把name传过去了。
console.log("Student")
}
getCode(){
console.log(this.code);
console.log(this.name)
}
}
var p1 = new Student("huo","18")
p1.getCode()
输出结果,注意顺序:
super调用People的构造函数→Student再执行→p1.getCode()再按顺序输出code和name。
第二个用法:可以调用父类的其他方法
class People {
mifan(){
console.log("吃米饭");
}
}
class Student extends People {
chifan(){
super.mifan();//直接通过super打点就可以调用父类的其他方法。
this.xuexi();
}
private xuexi() {
//这个方法本身是可以这在Student外部调用的,我想让他必须先吃饭再学习。
//也就是只让他在Student内部被调用,所以给他设置了访问控制符。
console.log("吃完米饭学习");
}
}
var p1 = new Student();
p1.chifan();
输出结果:
2、泛型
参数化的类型,一般来限制集合的内容。
class People {
constructor(public name:string){
};
}
class Student extends People {
constructor(name: string, public code:string){
super(name);
}
}
class Teacher extends People {
constructor(name: string, public code: string) {
super(name);
}
}
var arr: Array<People> = [];//<>中就是规定我这个arr数组只能存放跟People类型一样的数据
arr[0] = new Student("huo", "18");
arr[1] = new Teacher("huoqingchi", "23");
console.log(arr)
输出结果:
如果你存放其他类型的数据会有警告:
3、接口
用来建立某种代码约定,使得其它开发者在调用某个方法或创建新的类时必须遵循接口所定义的代码约定。
第一中用法:作为一个方法的参数类型的声明
//使用interface 来声明一个接口
interface jiekou {//接口的名字就交jiekou
name:string;
age:number;
}
class People{
constructor(public consig: jiekou){//让接口作为一个方法的参数类型的声明
}
}
var p1 = new People({
//当你去调用这个方法的时候TypeScript会去检查你传过去的参数是否符合接口所约定的格式。
name:"huoqingchi",
age:18
//参数不能多也不能少,如果没有值可以填null。
})
第二种用法:用接口来声明方法。
interface People {
chi();//People接口有个吃饭的方法。
}
class Student implements People {
//implements的意思是Student类实现People这个接口
//也就是它必须实现这个接口里面的方法。
chi(){
console.log("我吃素的");
}
}
class Teacter implements People {
chi(){
console.log("我吃肉的");
}
}
4、模块
模块可以帮助开发者将代码分割为可重用的单元。开发者可以自己决定将模块中的那些资源(类,方法,变量)暴露出去供外部使用,那些资源只能在模块内使用,一个文件就是一个模块。
./demo/ide/tscript/test.ts
export var a = 10;//export是暴露出去的意思。
var b = 20;//没有暴露出去的就只能在这个模块中使用。
export function fn1() {
console.log("我是fn1")
}
function fn2() {
console.log("我是fn2")
}
export class CLazz1 {
constructor() {
console.log("我是CLazz1类")
}
}
class CLazz2 {
constructor() {
console.log("我是CLazz2类")
}
}
./demo/ide/tscript/test2.ts
import { a, fn1, CLazz1} from './test';
//import是导入的意思,from是从哪里导入,{}中是导入那些东西。
console.log(a);
console.log(fn1);
console.log(CLazz1);
//一个模块中既可以import导入也可以export
export function fn3() {
console.log("我是fn3")
}
输出结果:
5、注解
注解为程序的元素(类,方法,变量)加上更直观明了的说明,这些说明信息与程序的业务逻辑无关,而是供指定的工具或框架使用的。
import {Component} from '@angular/core';//这里是用的angular,后续会增加vue,react。
@Component({//这里就是注解
selector:'app-root',
templaterUrl: './app.component.html',//加载到app.component.html页面中
styleUrls:['./app.component.css']//加载app.component.css样式文件
})
export class AppComponent {//当你用angular加载这个类的时候它会执行上面的注解
title = "app works!";
}
app.component.html
<h1>{{title}}</h1><!--页面会显示app works!-->
6、类型定义文件(*.d.ts)
类型定义文件用来帮助开发者在TypeScript中使用已有的JavaScript的工具包如:JQuery;
我们使用了typings,npm install -g typings 。
./demo/ide 在项目文件夹下。
打开CMD窗口运行typings install dt~jquery --global //这里是jquery举例,如果需要其它的记得更换。
其中”dt~”为使用DefinitelyTyped类型定义的意思,vscode可以识别这种定义。
没有安装之前:
安装之后:会自动生成typings文件夹
结束语
TypeScript的基础知识点我们就讲完了,后续根据反馈再整理更新。
TypeScript的文档:http://www.typescriptlang.org/docs/home.html
本人的博客:https://www.cnblogs.com/rope/
本人的github:https://github.com/RopeHuo
本人的邮箱:[email protected]
作者:Rope
|
请发表评论