1:安装ts前,必须先安装node.js
2:安装ts npm i typescript -g 全局安装
3:检验是否安装成功: tsc -v 若是显示版本便是安装成功
1:ts文件后面的后缀名为.ts
**注意点:ts代码被tsc转化后施直接生成一个.js文件,然后直接操作js文件即可(引入和操作等)**
2:ts需要转化为js文件,在导入html文件中才能使用==这导入的方式是:在文件中新建一个终端,然后输入tsc 文件名称.ts后缀==
以下更为合适:创建编译.ts文件,自动保存的配置
//在项目的终端,输入tsc --init 来创建ts工具的文件夹 tsconfig.json
//然后在tsconfig.json文件夹里面修改 "outDir": "./js", 编译完就保存在这个js文件夹里面
然后在终端-运行任务-typescript-tsc监视 ---点击之后,会生成一个js文件夹,里面包含.js文件
ts数据类型
1:ts语法规定:在声明遍历的时候,必须指定数据类型
语法 — let 变量名:数据类型
let age:number
let myName:string = “pink”
作用:这样声明数据类型,使得声明的变量只能存储这样的类型数据
2:ts的数据类型有:string number boolean array tuple(枚举) any(任意类型) null underfined void类型 never类型
注意点:underfined和null的是其他类型的子类,所以这两个变量的值可以赋给其他类型的变量
//1:boolean类型
let flag: boolean = true;
//2;number类型
let num: number = 123;
// num = "pin"; //出错
console.log(num);//123
//3:定义数组
let arr: number[] = [1, 3, 5, 7];
let arr2: string[] = ["pink", "lala", "pa"];
console.log(arr2);//["pink", "lala", "pa"]
//第二种方式
let arr3: Array = [1, 4, 7]
//4:元祖类型 (tuple) 也是数组中的一种 可以指定多种类型
let arr0: [string, number, boolean] = ["pom", 123, true]
//5 枚举类型 (enmu)
//可以定义flag 1为true -1为false 或者支付类型等 0未支付 1支付 2交易成功
enum Flag { success = 1, error = -1 }
let f: Flag = Flag.success;
console.log(f);//1
enum pay_status { nopay = 0, pay = 1, success = 2 };
let type: pay_status = pay_status.pay;
console.log(type);//1
enum Color { red, blur = 5, orange };
let x: Color = Color.orange;
console.log(x);//6
//6任意类型
let num2: any = 123;
num2 = "str";
console.log(num2);//str
//任意类型的作用: 需求对box盒子的文字改为红色
let oBox: any = document.querySelector(".box");
oBox.style.color = "red" //因为oBox是对象类型,但是ts中没有对象类型,因此使用any比较合适
//7: null (空) undefined (未定义) never(其他) 数据类型的子类型
let num: number | undefined;
// num = 123;
console.log(num);//123 //undefined 若是只定义为赋值的时候,输出undefined
//8:void类型---typescript中的void是表示没有任何类型,一般用于定义方法中方法没有返回值
function fun(): void {
console.log("run");
}
fun();
//如果有返回值的时候,就需要在函数后面添加数据类型
function fun1(): number {
return 123
}
fun1();
//9:其他类型,(包含null和undefined)的子类型,代表从不会出现的值。意味着声明never类型只能被never类型赋值,很少用
let b: null;
b = null;
let b3: undefined;
b3 = undefined;
//函数
//1:声明式函数
function fun(): string {
return "pin";
}
fun();
//2:匿名函数
let fun2 = function (): number {
return 123;
}
console.log(fun2());
//3:ts中定义方法传参
function getInfo(name: string, age: number): string {
return `${name}---的年龄为---${age}岁`;
}
console.log(getInfo("lala", 18));
//注意点:name和age定义了传入的参数必须是字符串,数字型,返回值的类型为string
let getInfo2 = function (name: string, age: number): string {
return `${name}---的年龄为---${age}`;
}
console.log(getInfo2("pon", 30));
function fun0(): void {//没有返回值的函数
console.log("run");
}
fun0();
//3.2:方法可选参数
//当给age参数添加一个?的时候,代表的是age属性可以传递也可以不传递
function getInfo3(name: string, age?: number): string {
if (age) {
return `${name}---的年龄为---${age}`;
} else {
return `${name}---的年龄为---保密`;
}
}
console.log(getInfo3("pip", 20));
//3.3:默认参数 es5中不可设置默认参数 但是es6和ts都可以设置默认参数
// 注意点:可选参数必须配置在最后面,就是类似直接把age设置为默认参数,直接给了默认值
function getInfo4(name: string, age: number = 20): string {
if (age) {
return `${name}---的年龄为---${age}`;
} else {
return `${name}---的年龄为---保密`;
}
}
console.log(getInfo4("pia")); //pia---的年龄为---20
console.log(getInfo4("pia", 30)); //pia---的年龄为---30
//3.4:剩余参数
//借助三点运算符 传递的参数转化为数组的形式
function sum(...result: number[]): number {
let sum = 0;
for (let i = 0; i < result.length; i++) {
sum += result[i]
}
return sum
}
console.log(sum(1, 2, 3, 4));//10
console.log(sum(1, 2, 3, 4, 5, 6));//21
//3.5:函数的重载
//在java中方法中的重载:重载指的是两个或者两个以上的同名函数,但是他们的参数不一样,这就是函数重载的现象。
//typescript的重载:通过为同一个函数提供多个函数类型定义来试下多种功能的目的
function getInfo0(name: string): string;
function getInfo0(age: number): number;
function getInfo0(str: any): any {
if (typeof str === "string") {
return "我的名字是" + str;
} else {
return "我的年龄是" + str
}
}
console.log(getInfo0("pink"));//我的名字是pink
console.log(getInfo0(40));//我的年龄是40
//另一种写法
function getInfo5(name: string): string;
function getInfo5(name: string, age: number): string;
function getInfo5(name: any, age?: any): any {
if (age) {
return "我的名字是" + name + "我的年龄是" + age;
} else {
return "我的名字是" + name
}
}
// console.log(getInfo5("paaa"));//我的名字是paaa
console.log(getInfo5("pa", 90));//我的名字是paaa 我的年龄是90
//3.6:箭头函数 this指向上下文
setTimeout(() => {
console.log("run");//run
}, 3000)
//1:es5中最简单的类
function Person() {
this.name = "pin";
this.age = 18;
}
let p = new Person();
console.log(p.age); //18
//2:构造函数和原型链中添加方法
function Person1() {
this.name = "pink";
this.age = 12;
this.run = function () {
console.log(this.name + "在运动");
}
}
//原型链上上面的属性会被多个实例共享 构造函数不会
Person1.prototype.sex = "男";
Person1.prototype.work = function () {
console.log(this.name + "在工作");
}
let p1 = new Person1();
p1.run(); //pink在运动
p1.work(); //pink在工作
//3:类的静态方法
function Person2() {
this.name = "pink";
this.age = 12;
this.run = function () {
console.log(this.name + "在运动");
}
}
//静态方法
Person2.getInfo = function () {
console.log("我是静态方法");
}
//原型链上上面的属性会被多个实例共享 构造函数不会
Person2.prototype.sex = "男";
Person2.prototype.work = function () {
console.log(this.name + "在工作");
}
let p2 = new Person2();
p2.work(); //pink在工作
//调用静态方法
Person2.getInfo();
//4-1:es5中 类的继承 通过对象的冒充方式
function Person3() { //父
this.name = "ppp";
this.run = function () {
console.log(this.name + "在run");
}
}
function Web() { //子 因为call方法用于继承,web继承了person3
Person3.call(this); //就是在调用Web函数的时候,借助call方法改变this指向,指向到父类Person3,
//但是没办法继承原型链上面的属性和方法
}
let w = new Web();
w.run(); //ppp在run
//4-2:es5中 原型链的继承
//注意点:原型链实现继承:可以继承构造函数里面的属性和方法,还可以继承原型链上面的属性和方法
function Person4() {
this.name = "qqq"
this.age = 12;
this.saiHi = function () {
console.log(this.name + "在说:" + "hi");
}
}
function Web2() {
}
Web2.prototype = new Person4(); //利用原型链的方式,来继承了构造函数的属性和方法
let w2 = new Web2();
w2.saiHi(); //qqq在说:hi
//4-2:es5中 原型链的继承 的问题
//实例化的时候,没办法给父类传递参数 因此需要原型链和冒充父类的方式来实现完美继承
function Person5(name, age) { //父
this.name = name
this.age = age;
this.saiHi = function () {
console.log(this.name + "在说:" + "hi"); //张一在说:hi
}
}
Person5.prototype.sex = "女";
Person5.prototype.work3 = function () {
console.log(this.name + "在工作"); //张一在工作
}
function Web3(name, age) { //子
Person5.call(this, name, age);
}
Web3.prototype = new Person5(); //利用原型链的方式,来继承了构造函数的属性和方法
let w3 = new Web3("张一", 20);
w3.saiHi();
w3.work3();
注意点:创建实例对象,便会触发对应类的构造函数,因此在实例对象中传入参数,被构造函数接受后,进行赋值
class Person {
name: string;//定义了属性
constructor(name: string) {//构造函数 实例化类的时候,触发该函数
this.name = name;
}
run(): void {
console.log(this.name);
}
}
let p = new Person("pink");//这边传递参数,实例化类后,触发构造函数,然后构造函数,接受传递过来的参数,进行赋值
p.run();//pink
使用entends来继承父类,并且在构造函数内使用super方法,来初始化父类的构造函数,两者结合,最终实现ts的继承
class Person {
name: string;
constructor(name: string) {
this.name = name;
}
run(): string {
return `${this.name}在运动`
}
}
// let p = new Person("liyi");
// console.log(p.run());//liyi在运动
//Web类来继承Person类
class Web extends Person {
constructor(name: string) {
super(name);//初始化父类的构造函数
}
}
let w = new Web("xiaoxie");
console.log(w.run());//xiaoxie在运动
注意点:父类和子类的方法一致,优先调用子类的函数,若是子类没有改属性或者改方法,则去父类寻找
class Person {
name: string;
constructor(name: string) {
this.name = name;
}
run(): string {
return `${this.name}在运动-父类`
}
work(): string {
return `${this.name}在工作-父类`
}
}
class Web extends Person {
constructor(name: string) {
super(name)
}
work(): string {
return `${this.name}在工作-子类`
}
}
let w = new Web("李侠");
console.log(w.run());//李侠在运动-父类
console.log(w.work());//李侠在工作-子类
typescript里面定义属性的时候,给我们提供了三种修饰符
public:公有 在类里面,子类 类外面都可以访问
protected: 保护类型 在类里面,子类都可以访问,但是在类外部不能访问
private:私有类型 在类可以访问,子类和类外部都不能访问
注意点:若是属性没有添加的那种类型的话,默认为共有属性
//1:public类型的访问
class Person {
public name: string;
constructor(name: string) {
this.name = name;
}
run(): string {
return this.name + "在run";
}
work(): string {
return this.name + "在工作";
}
}
class Web extends Person {//子类 利用super继承了父类
constructor(name: string) {
super(name)
}
work(): string {
return this.name + "在工作-子类"
}
}
let w = new Web("小谢");
console.log(w.work()); //小谢在工作 - 子类
console.log(w.name);//小谢 在类外面调用类的属性name
//2:protected类型的访问
class Person {
protected name: string;
constructor(name: string) {
this.name = name;
}
run(): string {
return this.name + "在run";
}
work(): string {
return this.name + "在工作";
}
}
class Web extends Person {//子类 利用super继承了父类
constructor(name: string) {
super(name)
}
work(): string {
return this.name + "在工作-子类"
}
}
let w = new Web("小谢");
console.log(w.work()); //小谢在工作 - 子类
// console.log(w.name);//报错 因为name为保护类型 在外面不能被访问
//3:private:私有类型 只能在本类中使用 子类和外部都不能访问
class Person {
private name: string;
constructor(name: string) {
this.name = name
}
run(): string {
return `${this.name}在run`
}
}
let p = new Person("小哈");
// console.log(p.name);//报错,因为name为私有类型,只能在类里面使用
console.log(p.run());//小哈在run 这是因为run在Person类里面,可以使用name属性
1:静态方法—就是使用static定义的方法,只能调用静态属性,调用静态方法—通过类.方法的方式调用
2:静态属性—就是使用static定义的属性
3:实例方法—就是通过实例对象调用的方法
4:实例属性—就是通过实例对象调用的属性
class Person {
public name: string;
static age: number = 10;
constructor(name: string) {
this.name = name;
}
run() {
console.log(this.name + "在run");
}
work() {
console.log(this.name + "在工作");
}
static print() {//静态方法,只能调用静态属性,不能调用类里面的属性
console.log("我是静态方法,今年" + this.age + "岁了");
}
}
let p = new Person("小谢"); //实例方法传入参数,触发构造函数,构造函数接受参数后赋值
p.work();//实例方法 就是实例化对象调用的方法 小谢在工作
Person.print();//调用静态方法 用static修饰的方法或者属性,直接通过类.调用 我是静态方法,今年10岁了
console.log(Person.age);//10
1:多态:是指父类定义的方法不去实现功能,而是通过继承的方式给了子类,子类继承父类的方法后,完成自己需要的功能,需要产生了多态性
需求 父类:动物类 子类:dog,cat继承了父类的吃的方法 输出狗吃肉,猫吃老鼠
class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
eat() {
}
}
class Dog extends Animal {
constructor(name: string) {
super(name)
}
eat() {
console.log(`${this.name}在吃肉`);
}
}
class Cat extends Animal {
constructor(name: string) {
super(name)
}
eat() {
console.log(`${this.name}吃老鼠`);
}
}
let dog = new Dog("小狗");
dog.eat();//小狗在吃肉
let cat = new Cat("猫");
cat.eat();//猫吃老鼠
2:抽象类:ts提供了抽象类,就是定义了这个类为抽象类,让子类继承抽象类的方法,值得注意的是:抽象类不能实例化,但是子类可以实例化。
abstract关键字定义了抽象类和抽象方法,抽象类中的方法不包含具体实现并且必须在派生类实现
abstract方法只能放在抽象类里面
抽象类和抽象方法来定义标准
需求: Animal这个类为抽象了 要求他的子类必须包含eat方法
abstract class Animal {//抽象类和抽象方法 不能直接实例化,只能被其他子类继承
public name: string;
constructor(name: string) {
this.name = name;
}
abstract eat(): any;
}
class Dog extends Animal {
//抽象类的子类,必须实现抽象类的方法
constructor(name: any) {
super(name)
}
eat() {
console.log(`${this.name}在吃肉`);
}
}
class Cat extends Animal {
constructor(name: any) {
super(name)
}
eat() {
console.log(`${this.name}在吃老鼠`);
}
}
let dog = new Dog("小狗");
dog.eat();//小狗在吃肉
let cat = new Cat("小花猫");
cat.eat();//小花猫在吃老鼠
接口的作用:接口就是一种规范的定义,它定义了行为和动作的规范。(对类里面的方法和属性定义了规范)
接口分为:
1:属性接口
2:加密函数类型—接口
3:可索引接口
4:类类型接口
5:接口的扩展
接口:行为和动作的规范,还可以对批量方法进行约束
需求:定义一个姓名的接口,里面必须传入性和名
interface FullName {//interface 为接口关键字
firstName: string;//接口中的对象是以;结束
lastName: string;
}
function printName(name: FullName) {
console.log(name.firstName + '---' + name.lastName);
}
function printInfo(info: FullName) {
console.log(info.firstName + '---' + info.lastName);
//不能添加,info.age 因为传入的参数info: FullName,需要符合FullName接口的规范
}
// printName({
// firstName: "小谢",
// lastName: "渣渣"
// }); //小谢---渣渣
// 推荐把对象写在外面 只有对象里面包含firstName和lastName即可,复用性高
let obj = {
age: 20,
firstName: "小谢",
lastName: "渣渣"
} //小谢---渣渣
printName(obj);
printInfo({
firstName: "李",
lastName: "仨"
}) //李---仨
接口—可选属性的定义 就是在定义接口的时候,对这个传入的参数设置为可选参数—以?设置
interface FullName {
firstName: string;
lastName?: string;
}
function getInfo(name: FullName) {
console.log(name.firstName + "-" + name.lastName);
}
getInfo({
firstName: "赵",
// lastName: "子龙"
})//赵-undefined 因为lastName为可选参数,但是打印的话,未定义传入的参数
元素js模拟封装jq的ajax接口
/*
KaTeX parse error: Expected '}', got 'EOF' at end of input: …ta: "{username:("#username").val(),content:$("#content").val()}",
dataType: “json”
})
*/
nterface Config {//配置的接口
type: string;
url: string;
data?: string;
dataType: string;
}
//原生js模拟jq封装的ajax
function ajax(config: Config) {
let xhr = new XMLHttpRequest();
xhr.open(config.type, config.url, true);
xhr.send(config.data);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
console.log("成功");
let str = xhr.responseText;
if (config.dataType === "json") {
JSON.parse(str)
console.log(JSON.parse(str));
} else {
console.log(xhr.responseText);
}
}
}
}
}
ajax({ //调用ajax接口
type: "get",
data: "name=lixi,age=20",
// url: "http://www.baidu.com",//跨域了
url: "http://a.itying.com/api/productlist",
dataType: "json"
})
interface encrypt {//encrypt ---加密
(key: string, value: string): string;
}
let md5: encrypt = function (key: string, value: string): string {
return key + "-" + value;
}
console.log(md5("name", "张三")); //name-张三
interface UesrArr {
[index: number]: string;
}
let arr: UesrArr = ["aa", "bb"];
console.log(arr[0]);//aa
erface Animal {
name: string;
eat(name: string): void;
}
class Dog implements Animal { //implements---生效执行 Dog类去实现Animal接口
name: string;
constructor(name: string) {
this.name = name;
}
eat() {
console.log(this.name + "在吃肉");
}
}
let dog = new Dog("小黑");
dog.eat();//小黑在吃肉
class Cat implements Animal {
name: string;
constructor(name: string) {
this.name = name;
}
eat(food: string) {
console.log(this.name + "吃" + food);
}
}
let cat = new Cat("小花猫");
cat.eat("猫粮");//小花猫吃猫粮
// interface Animal {
// eat(): void;
// }
// interface Person extends Animal {
// work(): void;
// }
// class Web implements Person {
// name: string;
// constructor(name: string) {
// this.name = name;
// }
// eat() {
// console.log(this.name + "吃肉");
// }
// work() {
// console.log(this.name + "在工作");
// }
// }
// let w = new Web("小谢");
// w.work();//小谢在工作
//继承并且实例化接口
interface Animal {
eat(): void;
}
interface Person extends Animal {
work(): void;
}
class Programmer {
name: string;
constructor(name: string) {
this.name = name;
}
coding(code: string): void {
console.log(this.name + code);
}
}
class Web extends Programmer implements Person {
// name: string;
constructor(name: string) {
// this.name = name;
super(name)
}
eat() {
console.log(this.name + "吃肉");
}
work() {
console.log(this.name + "在工作");
}
}
let w = new Web("小谢");
w.work();//小谢在工作
w.coding("写ts代码")//小谢写ts代码