# TypeScript **Repository Path**: josnfei/TypeScript ## Basic Information - **Project Name**: TypeScript - **Description**: TypeScript学习之旅 - **Primary Language**: TypeScript - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2018-10-02 - **Last Updated**: 2022-05-07 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## TypeScript学习笔记 ### 第01节:初识TypeScript - TypeScript是什么? + TypeScript 是一种由微软开发的自由和开源的编程语言。它是 JavaScript 的一个超集,TypeScript 在 JavaScript 的基础上添加了可选的静态类型和基于类的面向对象编程。 + 其实TypeScript就是相当于JavaScript的增强版,但是最后运行时还要编译成JavaScript。TypeScript最大的目的是让程序员更具创造性,提高生产力,它将极大增强JavaScript编写应用的开发和调试环节,让JavaScript能够方便用于编写大型应用和进行多人协作。 - TypeScript和JavaScript的对比 + TypeScript是一个应用程序级的JavaScript开发语言。(这也表示TypeScript比较牛逼,可以开发大型应用,或者说更适合开发大型应用) + TypeScript是JavaScript的超集,可以编译成纯JavaScript。这个和我们CSS离的Less或者Sass是很像的,我们用更好的代码编写方式来进行编写,最后还是有好生成原生的JavaScript语言。 + TypeScript跨浏览器、跨操作系统、跨主机、且开源。由于最后他编译成了JavaScript所以只要能运行JS的地方,都可以运行我们写的程序,设置在node.js里。 + TypeScript始于JavaScript,终于JavaScript。遵循JavaScript的语法和语义,所以对于我们前端从业者来说,学习前来得心应手,并没有太大的难度。 + TypeScript可以重用JavaScript代码,调用流行的JavaScript库。 + TypeScript提供了类、模块和接口,更易于构建组件和维护。 ### 第02节:开发环境的安装 - 1.安装Node.js - 2.安装TypeScript包 + `npm install typescript -g` + 苹果本请加上 `sudo`指令 + `tsc --version`查看版本号 - 3.编写HelloWorld程序 + `npm init -y` 先初始化项目 + `tsc --init` 生成一个`tsconfig.json`文件,它是一个TypeScript项目的配置文件,可以通过读取它来设置TypeScript编译器的编译参数。 + `npm install @types/node --dev-save` 安装,解决模块的声明文件问题。 + 最后编写 `helloWorld.ts` 进行保存 + 构建成普通的js文件, 点击vscode打开运行生成任务,然后选择tsc:构建-tsconfig.json,这时候就会生成一个helloWorld.js文件 + 在终端中输入node helloWorld.js就可以看到结果了。 ```javascript var a:string='Hello world' console.log(a) ``` ### 第03节:变量类型的那些事 - TypeScript中的数据类型有: + Undefined : + Number:数值类型; + string : 字符串类型; + Boolean: 布尔类型; + enum:枚举类型; + any : 任意类型,一个牛X的类型; + void:空类型; + Array : 数组类型; + Tuple : 元祖类型; + Null :空类型。 ```javascript // Undefined类型 // //声明数值类型的变量age,但不予赋值 // var age:number // console.log(age) //undefined // Number类型 // 所有的数字都是Number类型,这不分是整数还是小数。 // var age:number=18 // var stature:number=129.23 // console.log(age) // console.log(stature) // 在TypeScrip中有几种特殊的Number类型 我们需要额外注意一下: // NaN:它是Not a Number 的简写,意思就是不是一个数值。如果一个计算结果或者函数的返回值本应该是数值,但是由于种种原因,他不是数字。出现这种状况不会报错,而是把它的结果看成了NaN。 // Infinity :正无穷大。 // -Infinity:负无穷大。 // string类型 // 单引号或者双引号括起来的一串字符就是字符串 // var dfei:string='hello Dfei' // console.log(dfei) // boolean布尔类型 // boolean类型只有两种值,true和false。 // var a:boolean=true // var b:boolean=false // console.log(a) // console.log(b) // enum 类型 // 枚举类型(很多值是多个并且是固定的) // 世界上人的类型:男人、女人、中性 // enum Ren{nan,nv,yao} // console.log(Ren.yao) //2 和数组很像 // 如果我们想给这些枚举赋值,可以直接使用=,来进行赋值。 // enum Ren{ // nan='男', // nv='女', // yao='妖' // } // console.log(Ren.yao) //妖 // any类型 // 程序中不断变化着类型,又不想让程序报错,这时候就可以使用any // var t:any=10 // t='dfei' // t=true // console.log(t) //true // Null类型 // 与 Undefined 类似,都代表空。Null 代表是引用类型为空。意义不大,但是有用。后续学习中会使用到。 // 注意:剩余的数组 、元组、void 会在后续的章节中讲解。 ``` ### 第04节:TypeScript的函数 - 注意点 + 声明(定义)函数必须加 function 关键字; + 函数名与变量名一样,命名规则按照标识符规则; + 函数参数可有可无,多个参数之间用逗号隔开; + 每个参数参数由名字与类型组成,之间用分号隔开; + 函数的返回值可有可无,没有时,返回类型为 void; + 大括号中是函数体。 - TypeScript语言中的函数参数 + 1.有可选参数的函数 + 可选参数,就是我们定义形参的时候,可以定义一个可传可不传的参数。这种参数,在定义函数的时候通过?标注。 + 2.有默认参数的函数 + 有默认参数就更好理解了,就是我们不传递的时候,他会给我们一个默认值,而不是undefined了 + 3.有剩余参数的函数 + 有时候我们有这样的需求,我传递给函数的参数个数不确定 ```javascript // TypeScript的函数 // 定义函数 // function searchXJ(age:number):string{ // return '找到了'+age+'岁小姐姐' // } // var age:number=18 // var result:string=searchXJ(age) // console.log(result)//找到了18岁小姐姐 // console.log(searchXJ(age)) //找到了18岁小姐姐 // 注意: /** * 声明(定义)函数必须加 function 关键字; * 函数名与变量名一样,命名规则按照标识符规则; * 函数参数可有可无,多个参数之间用逗号隔开; * 每个参数参数由名字与类型组成,之间用分号隔开; * 函数的返回值可有可无,没有时,返回类型为 void; * 大括号中是函数体 **/ // TypeScript语言中的函数参数 // 函数的形参分为:可选形参、默认形参、剩余参数形参等。 // 1.有可选参数的函数 // 可选参数,就是我们定义形参的时候,可以定义一个可传可不传的参数。这种参数,在定义函数的时候通过?标注。 // function searchXJ(age:number,sc?:string):string{ // let yy:string='' // yy='找到了'+age+'岁' // if(sc!=undefined){ // yy=yy+sc // } // return yy+'的小姐姐' // } // let age:number=18 // let sc:string='大长腿' //可选参数,可以不传,不传里面也不会报错 // let result:string=searchXJ(age,sc) // console.log(result) //找到了18岁大长腿的小姐姐 // 2.有默认参数的函数 // 有默认参数就更好理解了,就是我们不传递的时候,他会给我们一个默认值,而不是undefined了 // function searchXJ(age:number=19,sc:string='大胸'):string{ // let yy:string='' // yy='找到了'+age+'岁' // if(sc!=undefined){ // yy=yy+sc // } // return yy+'的小姐姐' // } // let result:string=searchXJ() // console.log(result)//找到了19岁大胸的小姐姐 // 3.有剩余参数的函数 // 有时候我们有这样的需求,我传递给函数的参数个数不确定。 function searchXJ(...xuqiu:string[]):string{ let yy:string='找到了' for(let i=0;i{ return n1+n2 } console.log(add(1,2)) //3 ``` ### 第06节:函数中变量的作用域 - 认识全局变量和局部变量 + 局部变量:函数体内定义的变量就是局部变量。 + 全局变量: 函数体外 定义的变量就是全局变量。 - 局部变量和全局变量重名 + 当局部变量与全局变量重名的时候,在函数体内是局部变量起作用;如果重名,就有变量提升,这是一个坑,小伙伴们必须要注意 - let关键字变量的作用域 + 在早期javascript的变量作用域只有全局和局部,并且是以函数划分的,但在其他语言中,作用域的划分是以一对大括号作为界限的。 + 所以,JavaScript就遭到了无数开发者的吐槽,甚至说javascript不适合开发大型语言,容易内存溢出。JavaScript团队意识到了这一点,在ES6中推出了let关键字。 + 使用let关键字的变量就是一个块级作用域变量。希望大家在实际工作中多使用let来声明你的变量,让你的程序更有条例。 来看一端程序: + 注意: 块级作用域是let,但是因为在ts转换为es5的时候会变成var,导致失效,实际是访问不到的,具体看最下面的代码,把编辑好的ES5里面的变量声明改成let,就可以知道结果 - 函数的类型为:`void`,是当函数不想要任何返回值得时候,这样子写 ```javascript // 第06节:函数中变量的作用域 // 函数作用域演示 // 我们来举个例子,现在要制作一个整形的方法,然后在函数里用var定义一个yangzi的变量,我们再函数的外部读取这个变量,你会发现是读取不到的。 // function zhengXing():void{ // var yangzi = '刘德华' // console.log(yangzi) // } // zhengXing() // console.log(yangzi) // 认识全局变量和局部变量 // 局部变量:函数体内定义的变量就是局部变量。 // 全局变量: 函数体外 定义的变量就是全局变量。 // 我们改造上边的程序,把yangzi办理移动到全局,然后再进行输出。 // var yangzi = '刘德华' // function zhengXing():void{ // console.log('技术胖整形成了'+yangzi+'的样子') // } // zhengXing() // console.log(yangzi) // 这时候yangzi变量是全局的,所以在函数内也可以调用,在函数外也可以调用。 // 局部变量和全局变量重名 // 当局部变量与全局变量重名的时候,在函数体内是局部变量起作用;如果重名,就有变量提升,这是一个坑,小伙伴们必须要注意 // 还是上边整形的例子,技术胖是想整形成刘德华,但是函数体内部声明了一个马德华。虽然一字之差,但是样子可是完全不同的。我们来看代码如何实现: // var yangzi:string = '刘德华' // function zhengXing():void{ // var yangzi:string = '马德华' // console.log('技术胖整形成了'+yangzi+'的样子') // } // zhengXing() // console.log(yangzi) // 这回你会发现,技术胖并没有变成刘德华而是变成了马德华。那你说我我想变成刘德华,我在函数没声明新变量前打印到控制台行不行? // var yangzi:string = '刘德华' // function zhengXing():void{ // console.log('技术胖整形成了'+yangzi+'的样子') // var yangzi:string = '马德华' // console.log('技术胖整形成了'+yangzi+'的样子') // } // zhengXing() // console.log(yangzi) // 代码改造成了这样,但是你会发现,我们输出的结果如下: // 技术胖整形成了undefined的样子 // var yangzi:string = '刘德华' // function zhengXing():void{ // var yangzi:string // console.log('技术胖整形成了'+yangzi+'的样子') // yangzi = '马德华' // console.log('技术胖整形成了'+yangzi+'的样子') // } // zhengXing() // console.log(yangzi) // 也就是当内部声明了和全局的变量同名时,就会出现变量提升的效果,声明语句会提升到函数的第一句。这就是著名的变量提升效果。 // let关键字变量的作用域 // 在早期javascript的变量作用域只有全局和局部,并且是以函数划分的,但在其他语言中,作用域的划分是以一对大括号作为界限的。 // 所以,JavaScript就遭到了无数开发者的吐槽,甚至说javascript不适合开发大型语言,容易内存溢出。JavaScript团队意识到了这一点,在ES6中推出了let关键字。 // 使用let关键字的变量就是一个块级作用域变量。希望大家在实际工作中多使用let来声明你的变量,让你的程序更有条例。 来看一端程序: function zhengxing():void{ var yangzia:string='刘德华' { let yangzib:string='周德华' console.log('我整容成了'+ yangzib) } console.log('我整容成了'+yangzia) console.log('我整容成了'+yangzib) } zhengxing() ``` ### 第07节:引用类型-数组 - TypeScript中也给我们提供了一些引用类型 + Array(数组)、String(字符串)、Date(日期对象)、RegExp(正则表达式)等 - 初始化数组的两种方法 + `let arr1:number[]` //声明一个数值类型的数组 + `let arr2:Array` //声明一个字符串类型的数组 - 给数组赋值的两种方法 + 字面量赋值法 比如:`et arr2:number[] = [1,2,3,4,5]` + ypeScript中指定数据类型的数组只能存储同一类型的数组元素。 + 也就是初始化的时候,是什么类型,就是什么类型,否则报错 + 构造函数赋值法 比如:`let arr3:Array = new Array('jspang','技术胖','金三胖')` - 认识元祖,一种特殊的数组 + 元祖是一种特殊的数组,元祖类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同 + 两点: 知道类型,和数量(个数) + 实际开发中,很少用 ```javascript // 第07节:引用类型-数组 // 初识引用类型 // let jspang={ // name:'技术胖', // website:'jspang.com', // age:19, // saySomeing:function(){ // console.log('为了做前端') // } // } // console.log(jspang.name) // jspang.saySomeing() // TypeScript中也给我们提供了一些引用类型 /** * Array(数组)、String(字符串)、Date(日期对象)、RegExp(正则表达式)等 * */ // 初始化数组的两种方法 // 声明数组的方法 // let arr1:number[] //声明一个数组类型的数组 // let arr2:Array //声明一个字符串类型的数组 // 给数组赋值 // 字面量赋值法:直接使用“[ ]”对数组进行赋值。 // 构造函数赋值法: // 字面量赋值法 // 定义一个空数组,数组容量为0 // let arr1:number[]=[] // // 定义一个数组,并且直接给数组赋值 // let arr2:number[]=[1,2,3] // // 定义一个数组,同时给数组赋值 // let arr3:Array=['就好','回教室了'] // let arr4:Array=[true,false] // // 需要注意的是,在TypeScript中指定数据类型的数组只能存储同一类型的数组元素。 // // 报错!必须存储number类型的数据 // let arr5:number[]=[1,2,'dfd'] // let arr1:Array=[12,34,12] // let arr2:boolean[]=[true,false] // console.log(arr1) // console.log(arr2) // 总结,数组的什么可以用 let arr1:类型[]=[]或者let arr1:Array<类型>=[]这样的形式 // 构造函数赋值法 // 在 TypeScript 中使用 Array 这个引用类型来表示数组的,那么每一个数组都是 Array 类型的实例。那么,我们在创建数组的时候也可以使用构造函数来进行赋值。 // let arr1:number[]=new Array() // let arr2:number[]=new Array(1,2,3) // let arr3:Array=new Array('1','2') // let arr4:Array=new Array(true,false) // console.log(arr1) // console.log(arr2) // console.log(arr3) // console.log(arr4) // 这两种方法,都可以给数组进行赋值,在实际开发中使用哪种方法都是可以的。 // 认识元祖,一种特殊的数组 // 元祖是一种特殊的数组,元祖类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同。比如,你可以定义一对值分别为string和number类型的元祖。元祖在实际开发中使用的非常少,大家了解一下就可以了,不做过多介绍。 // 声明一个元祖 let x:[string,number] // 正确的初始化 x=['fldsj',12] // // 错误的初始化 // x=[2,'hfljkds'] // TypeScript中其它的数组知识跟JavaScript中的一样 ``` ### 第08节:引用类型-字符串 - 字符串的两种类型 + 基本类型字符串:由单引号或者双引号括起来的一串字符串。 + 引用类型字符串:用new 实例化的 String类型。 + 那为什么会出现这种情况那,有的小伙伴会认为是不是当时JavaScript的开发人员脑子进水了。其实不是的,在前端开发,操作字符串是最普遍的一种操作。JavaScript的开发人员为了大家更容易的操作字符串,有了引用类型的字符串就可以给字符串增加一系列方法了。 - 基本类型的字符串可以直接使用引用类型的属性和方法。 - 字符串常用的方法 + 字符串的长度length + 查找字符串 + 基本语法:`str.indexOf(subStr)` + 查找的字符串没有找到,则返回-1 + 字符串尾部开始查找字符串的位置,使用`lastIndexOf()` + 需要注意的是,`lastIndexOf()`,并不是返回从后到前的下标位置。这个新手很容易采坑。 + 截取字符串 + 基本语法如下:`str.substring(startIndex,[endIndex])` + 参数 startIndex 表示开始下标,endIndex 表示结束下标,endIndex 参数是可选的 + 该方法的作用是从指定的开始下标开始截取字符串,截取到 endIndex 的下标之前,如果没有 endIndex,则截取到字符串结束。 + 替换字符串 + 基本语法如下:`str.replace(subStr,newstr);` + substr 表示被替换的子串,newstr 表示要替换成的子串 + 该方法的作用是在 str 中从头部开始找 substr 子串,找到之后,把 substr 用 newstr 替换掉。 + 需要注意的是如果 str 中有多个 substr 子串,只有第一个 substr 子串会被替换掉。 ```javascript // 第08节:引用类型-字符串啊 // 字符串的两种类型 // 基本类型字符串:由单引号或者双引号括起来的一串字符串。 // 引用类型字符串:用new 实例化的 String类型。 // let jspang:string='jspang' // let jspanga:String=new String('jspanga') // console.log(jspang)// jspang // console.log(jspanga)// [String: 'jspanga'] // 需要说明的是这两种声明字符串的方法没有什么不同。基本类型的字符串可以直接使用引用类型的属性和方法。 // 字符串的长度length // console.log(jspang.length) //6 // console.log(jspanga.length) //7 // 字符串常用的方法 // 查找字符串 // 基本语法:str.indexOf(subStr) // let something:string = "清早起来打开窗,心情美美的,我要出去找小姐姐,心情美美的。" // let xiaoJieJie:string = "小姐姐" // console.log(something.indexOf(xiaoJieJie)) //19 // // 如果我们查找的字符串没有找到,则返回-1。 // // 从字符串尾部开始查找字符串的位置,使用lastIndexOf( ) // console.log(something.lastIndexOf(xiaoJieJie)) //19 // 需要注意的是,返回的都是字符串的下标。所以返回的值是相同的。并不是返回从后到前的下标位置。这个新手很容易采坑。 // 截取字符串 // str.substring(startIndex,[endIndex]) // 参数 startIndex 表示开始下标,endIndex 表示结束下标,endIndex 参数是可选的。 // let something:string = "清早起来打开窗,心情美美的,我要出去找小姐姐,心情美美的。" // let xiaoJieJie:string = "小姐姐" // console.log(something.substring(8)) // console.log(something.substring(8,14)) // 替换字符串 // str.replace(subStr,newstr); // substr 表示被替换的子串,newstr 表示要替换成的子串。该方法的作用是在 str 中从头部开始找 substr 子串,找到之后,把 substr 用 newstr 替换掉 // 需要注意的是如果 str 中有多个 substr 子串,只有第一个 substr 子串会被替换掉。 let something:string = "清早起来打开窗,心情美美的,我要出去找小姐姐,心情美美的。" let xiaoJieJie:string = "小姐姐" console.log(something.replace(xiaoJieJie,'小哥哥')) ``` ### 第09节:引用类型-日期对象 - TypeScript中使用Date这个引用类型来存储日期对象,如果你要声明一个日期变量时,记得也要注明它的类型是Date。 - 创建日期对象 + 日期对象是Date的实例,可以使用构造函数的方法进行创建。并且构造函数中可以传递多种类型的参数。 + `let d:Date = new Date()` - 日期对象传的参数 1. 不传递任何参数 + `let d:Date = new Date()` 2. 传递一个整数 + 传递一个整数,这个整数代表的是距离1970-01-01 00:00:00的毫秒数(具体为什么是这个时间,小伙伴可以自己百度一下)。 + 例如:传入参数为1000,将创建一个表示1970-01-01 00:00:01的日期对象。 3. 传递一个字符串 + 如果传递一个表示日期的字符串,就会生成相对应的日期对象。 + 字符串的格式常用: 1. yyyy/MM/dd hh:mm:ss 2. yyyy-MM-dd hh:mm:ss 3. yyyy-MM-ddThh:mm:ss + 开发中你不用太过于纠结使用哪种方式进行声明 4. 传递表示年月日时分秒的变量 + `let d:Date = new Date(year,month,day,hours,minutes,seconds,ms);` + year 表示年份,4位数字。 + month表示月份,数值是0(1月)~11(12月)之间的整数。 + day 表示日期。数值是1~31之间的整数。 + hours 表示小时,数值是0-23之间的整数。 + minutes 表示分钟数,数值是0~59之间的整数。 + seconds 表示秒数,数值是0~59之间的整数。 + ms 表示毫秒数,数值是0~999之间的整数。 ```javascript // 第09节:引用类型-日期对象 // 创建日期对象 // 1.不传递任何参数 // var d:Date=new Date() // console.log(d) //2018-10-02T14:09:24.312Z // 2.传递一个整数 // var d:Date=new Date(1000) // var e:Date=new Date(2000) // console.log(d)//1970-01-01T00:00:01.000Z // console.log(e)//1970-01-01T00:00:02.000Z // 3.传递一个字符串 // 字符串的格式常用:yyyy/MM/dd hh:mm:ss,yyyy-MM-dd hh:mm:ss,yyyy-MM-ddThh:mm:ss等, // let d1:Date=new Date('2018/10/02 22:30:12') // let d2:Date=new Date('2018-10-02 22:30:12') // let d3:Date=new Date('2018-10-02T22:30:12') // console.log(d1)//2018-10-02T14:30:12.000Z // console.log(d2)//2018-10-02T14:30:12.000Z // console.log(d3)//2018-10-02T14:30:12.000Z // 4.传递表示年月日时分秒的变量 //year 表示年份,4位数字。 //month表示月份,数值是0(1月)~11(12月)之间的整数。 //day 表示日期。数值是1~31之间的整数。 //hours 表示小时,数值是0-23之间的整数。 //minutes 表示分钟数,数值是0~59之间的整数。 //seconds 表示秒数,数值是0~59之间的整数。 //ms 表示毫秒数,数值是0~999之间的整数。 let year:number=2018 let month:number=10 let day:number=2 //不能写成02,写成2 let hours:number=22 let minutes:number=20 let seconds:number=37 let ms:number=888 let d:Date=new Date(year,month,day,hours,minutes,seconds,ms) console.log(d) //2018-11-02T14:20:37.888Z ``` ### 第10节:引用类型-正则表达式 - 创建正则表达式两种方法 + new关键字的构造函数方法 + 字面量的方式 - new关键字的构造函数方法 + 可以传一个参数,也可以传递两个参数 + 一个是字符串描述,另一个是修饰符 + 比如g是全局修饰符,i是忽略大小写,m是多行模式。 + `let reg1:RegExp = new RegExp("jspang")`表示字符串规则里含有jspang + `let reg2:RegExp = new RegExp("jspang",'gi')` - 字面量法 + `let reg3:RegExp = /jspang/` + `let reg4:RegExp = /jspang/gi` - RegExp中的常用方法 + `test(string)` :在字符串中查找是否存在指定的正则表达式并返回布尔值,如果存在则返回 `true`,不存在则返回 `false`。 + `exec(string)` : 用于在字符串中查找指定正则表达式,如果 exec() 方法执行成功,则返回包含该查找字符串的相关信息数组。如果执行失败,则返回 `null`。 ```javascript // 第10节:引用类型-正则表达式 // 创建正则表达式也提供了两种方法 // 才采用new 关键字 // 另一种是采用字面量的方式 // 构造函数法 // 构造函数中可以传一个参数,也可以传递两个参数。一个是字符串描述,另一个是修饰符,比如g是全局修饰符,i是忽略大小写,m是多行模式。 // let reg1:RegExp=new RegExp('jspang') //表示字符串里含有jspang // console.log(reg1) // /jspang/ // let reg2:RegExp=new RegExp('jspang','gi') // console.log(reg2)// /jspang/gi // 字面量方法 // let reg1:RegExp=/jspang/ // let reg2:RegExp=/jspang/gi // RegExp中的常用方法 // test(string) :在字符串中查找是否存在指定的正则表达式并返回布尔值,如果存在则返回 true,不存在则返回 false。 // exec(string) : 用于在字符串中查找指定正则表达式,如果 exec() 方法执行成功,则返回包含该查找字符串的相关信息数组。如果执行失败,则返回 null。 // test let reg1:RegExp=/jspang/gi let website:string='jspang.com' // let result:boolean=reg1.test(website) // console.log(result) //true // exec(string) console.log(reg1.exec(website)) // [ 'jspang', index: 0, input: 'jspang.com' ] ``` ### 第11节: 面向对象编程-类的声明和使用 - 说在前面 + TypeScript提供了强大的类的支持,作为一个程序员一定要学会类的使用,因为只有会了类才可以new出对象来,否者可能会单身一辈子哦(开个玩笑) + 类的出现可以让前端程序员抽象层次、增加维护性和复用性。当然这一系列的类的操作,我们都叫他面向对象编程。 + TypeScript就是一个基于类的面向对象编程语言。 - 认识类与对象 + 类是对象具体事务的一个抽象,对象是类的具体表现。 + 举例 + 有人给你介绍对象,会问你的要求。那么,你的要求是:身高165以上,体型偏瘦,长头发,大眼睛。从事正当稳定的工作,会做饭等等。这些要求就是对你心中理想伴侣的一个抽象,就是类。介绍人按照你的要求给你找的这些女生,就是类的实例,就是对象。 - 类的定义 + class关键字声明了一个类 + 使用和定义类其实很简单,关键是理解类的思想。要有抽象逻辑的能力,这样才能复用和增强维护性。 + constructor为构造函数。构造函数的主要作用是给类中封装的属性进行赋值。 - 类其实和ES6你们的类很像 ```javascript // 第11节: 面向对象编程-类的声明和使用 // 类的定义 class xiaojiejie{ name:string; age:number; constructor(name:string,age:number){ //为类里面的属性进行赋值 this.name=name; this.age=age; }; say(){ console.log('小哥哥好') } } let jiejie:xiaojiejie=new xiaojiejie('范冰冰',18) console.log(jiejie) //xiaojiejie { name: '范冰冰', age: 18 } jiejie.say()//小哥哥好 ``` ### 第12节: 面向对象编程-修饰符 - 说在前面 + 类中的修饰符是最常见的,TypeScript为我们准备了丰富的修饰符, - 访问修饰符 + public:公有修饰符,可以在类内或者类外使用public修饰的属性或者行为,默认修饰符。 + protected:受保护的修饰符,可以本类和子类中使用protected修饰的属性和行为。 + private : 私有修饰符,只可以在类内使用private修饰的属性和行为。 - 只读属性修饰符 + 使用readonly修饰符将属性设置为只读 + 只读属性必须在声明时或者构造函数里被初始化(注意) ```javascript // 第12节: 面向对象编程-修饰符 // class xiaojiejie2{ // public sex:string; // protected name:string; // private age:number; // public constructor(sex:string,name:string,age:number){ // this.sex=sex; // this.name=name; // this.age=age; // }; // public sayHello(){ // console.log('小哥哥好') // }; // protected sayLove(){ // console.log('我爱你') // } // } // let jiejie2:xiaojiejie2=new xiaojiejie2('女','迪丽巴热',19) // console.log(jiejie2.sex) // console.log(jiejie2.name) //报错 // console.log(jiejie2.age) //报错 // jiejie2.sayHello() // jiejie2.sayLove() //报错 // 只读属性修饰符 class Man{ public readonly sex:string='男' } let man:Man=new Man() console.log(man.sex) man.sex='女' //报错,并且改不了 ``` ### 第13节: 面向对象编程-继承和重写 - 说在前面 + 在使用TypeScript这门语言时,一个最重要基本功就是面向对象编程,那对类的扩展就变的格外重要,扩展经常使用的手段就是继承。 - 类的继承 + 继承:允许我们创建一个类(子类),从已有的类(父类)上继承所有的属性和方法,子类可以新建父类中没有的属性和方法。 + `extends`关键字就是继承的重点 - 类方法的重写 + 先是继承了父类的方法,然后通过`super`关键字调用了父类的方法 ```javascript // 第13节: 面向对象编程-继承和重写 // 类的继承 // 父类 class JSpang{ public name:string; public age:number; public skill:string; constructor (name:string,age:number,skill:string){ this.name=name; this.age=age; this.skill=skill }; public interest(){ console.log(this.name+'找小姐姐') } } let jspangObj:JSpang=new JSpang('技术胖',20,'web') jspangObj.interest() // 子类继承 extends 和类方法重写 // 他不仅完全继承了我的基因,还增加了帅气的属性和赚钱的本领 class JSshuai extends JSpang{ public zhangxiang:string='帅气'; public interest(){ // super.interest() //super关键字调用了父类的方法,并且实现技能增加,如果注释这句话,那就相当于,父亲的找小姐姐不会输出了 console.log('建立电商平台') } public zhuangqiang(){ console.log('一天赚一个亿') } } let JSshuaiObj=new JSshuai('技术帅',4,'演讲') console.log(JSshuaiObj) JSshuaiObj.interest() JSshuaiObj.zhuangqiang() ``` ### 第14节:面向对象编程-接口 - 在面向对象的语言中,术语interface经常被用来定义一个不包含数据和逻辑代码但是用来签名定义了行为的抽象类型。 - 定义接口的关键字是`interface` - 可选参数的接口`maiBaoBao?:Boolean` ? 号的形式代表可选,和函数参数里面的可选参数方式是一样的 - 规范函数类型接口 + 我们还可以使用接口来规范函数类型的接口,比如现在要找老公这件事,我们规定有一些资源,然后我们需要哪些资源,在函数中进行匹配,最后返回是否匹配成功。 - 接口还可以规范类,但形式都和上满讲的差不多 ```javascript // 第14节:面向对象编程-接口 // 认识接口 interface zhaolaogong{ sex:string; interest:string; maibaobao?:boolean //可选参数 } let myzlg:zhaolaogong={sex:'男',interest:'看书,画画'} console.log(myzlg) //{ sex: '男', interest: '看书,画画' } // 规范函数类型接口 interface searchMan{ (source:string,beitai:string):boolean // source代表资源,beitai代表是否属于资源里面的东西, 函数返回布尔值 } let mysearchMan:searchMan // 按规范使用,并且返回布尔值 mysearchMan=function(source:string,beitai:string):boolean{ let flag=source.indexOf(beitai) return flag!=-1 } // 调用 console.log(mysearchMan('高、富、帅、大','壮')) //false ``` ### 第15节:面向对象编程-命名空间 - 在制作大型应用的时候,为了让程序更加有层次感和变量之间不互相干扰,我们可以使用命名空间来构建程序。 + 举个小例子:比如“德华”这件事,帅哥也有叫德华的,二师兄也有叫德华的。那我们要如何区分那。这对于女孩子选老公来说非常重要啊。 - 当然命名空间就是解决这个问题的,命名空间,又称内部模块,被用于组织有些具有内在联系的特性和对象。 ```javascript // 第15节:面向对象编程-命名空间 // 命名空间的使用 namespace shuaige{ export class dehua{ public name:string='刘德华' talk(){ console.log('我是刘德华') } } } namespace bajie{ export class dehua{ public name:string='马德华' talk(){ console.log('我是二师兄马德华') } } } let dehua1:shuaige.dehua=new shuaige.dehua() let dehua2:bajie.dehua=new bajie.dehua() dehua1.talk() //我是刘德华 dehua2.talk() //我是二师兄马德华 ``` ### 总结 - 从类开始,写法都是`let 变量:类名=new 类()` - 具体写法有时候忘记的,具体用到,多回来看看具体写法, #### 最后 - 国庆为毛码云好像挂了,上传代码老是403错误,超时`Operation timed out`,网站也打不开,真心想吐槽