初探TypeScript
Posted ㄏ、Forgetˊ
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了初探TypeScript相关的知识,希望对你有一定的参考价值。
TypeScript菜鸟学习笔记
TypeScript是什么?
TypeScript = Type + EcmaScript6
TypeScript是javascript的强类型版本。然后在编译器去掉类型和特有语法,生成纯粹的Javascript的代码。由于最终在浏览器中运行的仍然是Javascript,所以TypeScript并不依赖于浏览器的支持,也不会带来兼容性的问题。
TypeScript是Javascript的超集,这意味着他支持所有的JavaScript语法。并在此之上对JavaScript添加了一些拓展,如class/interface/module等。这样会大大提升代码的可阅读性。
和JavaScript弱类型不同,TypesScript这种强类型语言最大的优势在于静态类型检查,可以在代码开发阶段就预知一直低级错误的发生。
学习typescript的前置知识:
- EcmaScript6语法基础
- TypeScript概念及与JavaScript关系 如同CSS和less、sass之间的关系
- 具有一定的JavaScript开发经验
- 有C#、C、C++、Java等静态类型语言开发经验更佳
TypeScript与传统JavaScript的区别
举个最简单的例子,新建一个js文件,粘贴下面的代码:
let foo =
name: 'bar'
console.log(foo.naem)
上述JS代码中,定义了一个foo对象,其中有一个name属性,而在console打印的时候,却是打印foo.naem,这个时候,程序是不会报错的。
我们把后缀js替换为ts(这里默认你已经全局安装了TypeScript)
妈妈再也不用担心我写代码拼错单词了有木有?
解构赋值
解构赋值分两种,一个是数组的解构赋值,一个是对象的解构赋值,其实数组也是对象的一种。
假设现在有一个数组,需要分别取数组中的元素,通常情况下我们会这么写:
let arr = [10, 20]
let arr1 = arr[0]
let arr2 = arr[1]
使用TypeScript我们可以换成这样:
let arr: number[] = [10, 20]
let [arr1, arr2] = arr
同理换成对象的话,我们可以这么写:
let user =
name: 'jack',
age: 2
// 由于window实例对象上也存在name属性,故这里的name我们需要给它一个别名
// 这里的name: nickname不是类型定义,而是解构的时候给name起一个别名为nickname
let name: nickname, age = user
我们将其应用到函数中:
// 通常写法
function add(arr: number[]): number
let x = arr[0]
let y = arr[1]
return x + y
add([10, 20])
// 解构写法
function add([x, y]): number
return x + y
add([10, 20])
剩余参数
剩余参数的使用依赖于ES6的...
拓展操作符
// 假设现在有一个sum方法,用户直接传参计算,我们可以这么写
function sum(...args: number[])
let result = 0
args.forEach((item) =>
result += item
)
return result
// 调用的时候,我们只需要直接传参即可
sum(1, 2, 3, 4)
// 数组中的应用
let arr1 = [1, 2, 3]
let arr2 = [4, 5, 6, ...arr1] // 数组arr2合并数组arr1
let arr = [...arr1, ...arr2] // 数组arr1和arr2合并
// 对象中的应用
// 假如说有各有obj1和obj2对象,对象obj2也具备obj1中的属性,那我们可以这么写
let obj1 =
foo: 'bar'
let obj2 =
...obj1, // obj1直接通过拓展操作符写入obj2
name: 'Jack'
类的基本使用
假设我们现在有一个Person类,它具有name、age属性和一个sayHello方法,这里我们先使用函数的方式来实现它
function Person(name: string, age: Number)
this.name = name
this.age = age
// 通过prototype给Person实例追加一个sayHello方法
Person.prototype.sayHello = function (): void
console.log('Hello')
如果我们使用class关键字来定义的话,我们可以把上边的代码换成这样:
class Person
name: string
age: number
// constructor就是类的构造函数
// 当你调用new Person 的时候就会调用constructor(返回值为Person实例对象)
constructor(name: string, age: number)
// 我们这里实际上是动态地添加成员
// TypeScript要求类的成员必须先定义出来并确定类型
this.name = name
this.age = age
// 实例方法
sayHello(): void
console.log('Hello')
// 然后我们需要通过new关键字来使用它
let p1 = new Person('张三', 18) // new出一个p1实例
p1.sayHello() // 调用实例方法
从代码量来看,其实是增加了,但是使用class来创建类,比起用function来实现清晰很多。
在实际开发中,我们肯定不止有一个类,如果有多个类,而且类之间存在相同可继承的属性或者方法,我们可以使用类的继承关键字extends
来继承类:
// 假如说有一个Person类,它里面有一个eat方法
class Person
name: string
age: number
constructor(name: string, age: number)
this.name = name
this.age = age
eat()
console.log('吃饭')
// Student class需要继承Person class
class Student extends Person
constructor(name: string, age: number)
super(name, age) // 父类构造函数
new Student('张三', 18) // 这里我们就可以拿到Person类和Student类中公开的属性和方法
类成员访问修饰符
类成员默认都是公开的,默认都是public
(写不写无所谓)
private
私有的 私有成员无法被继承 (作用:可以把不希望被外部修改的成员设置为私有成员)
protected
受保护的 和private
类似,外部无法访问,但是可以被继承
还有一个比较特殊的 readonly
只读的,不允许修改,和const
定义常量类似
class Person
public name: string
age: number
// 我们可以在声明类成员的时候同时为其赋值
private readonly type: string = '人类'
// 和private类似,外部无法访问,但是可以继承
protected foo: string = 'bar'
// 方法默认也是public公开的
getType()
// private和protected修饰的属性,只能在内部访问
console.log(this.type)
changeType()
// type为readonly只读的,这里这么写系统会抛出警告,type不可被修改
this.type = '哈哈哈'
class Student extends Person
getFoo()
// foo属性在父类中为受保护的,它可以被继承
// 不能从外界访问,但可以从内部访问foo
console.log(this.foo)
// 修饰符的各种写法
class Person
// 最基础的写法
public name: string
public age: number
constructor( name: string, age: number)
// 简写
constructor(public name: string, public age: number)
// 也可以混写
public gender: string
constructor(public name: string, public age: number, gender: string)
类中属性的get和set
假设现在定义了一个Person类,它有一个age属性,我们在new实例的时候,为age传值为-10。这样做的话,虽然程序上不会报错,可是业务逻辑上却出错了,因为人的年龄是不存在负数的,我们需要在new之前进行判断。
class Person
public age: number
constructor()
// 可在此手动校验
new Person().age = -10
但其实,我们可以使用类中属性的get和set来进行校验
class Person
private _age: number
get age()
return this._age
set age(val)
if (val < 0)
// 判断到传入的age值小于0,则抛出Error
throw new Error('年龄不能小于0岁')
// 在校验正确后,我们才对其做赋值操作
this._age = val
let p1 = new Person()
p1.age = -10 // 这里赋值,就会先p1实例的set方法
类的静态成员
实例成员,只能通过new出来的实例访问
静态成员,也叫类的成员,只能通过类去访问
class Person
static type: string = '人类'
name: string = '张三'
age: number = 18
// 默认是实例成员,加上static就会变成静态成员
static sayHello()
console.log('我是人类')
// 访问静态成员,只能通过类去访问
// 如访问Person类中的type属性和sayHello方法
console.log(Person.type)
Person.sayHello()
迭代器
for-of迭代的是对象的键所对应的值, for-in迭代的是对象的键的列表
let arr = [1, 2, 5]
for (let val of arr)
console.log(val) // for-of迭代输出的是对象的键所对应的值,这里输出 1 2 5
for (let key in arr)
console.log(key) // for-in迭代输出的是对象的键的列表(在这里就是数组的下标值),这里输出 0 1 2
总结
经过简单的学习,我们了解到了TypeScript强大的类型校验对JavaScript所带来的功能增强,但是并不是说它就是万能的,我们仍需要以实际环境来判断是否需要(必须)使用TypeScript。
这里有几点总结概况:
- TypeScript 未能带来预期的结果或价值,如开发人员学习成本过高、小团队小项目,那么这种情况下其实不推荐使用;
- 只有当 TypeScript 提供了你预期的那些好处时才有自己的价值,否则结果会变得很糟糕;
- 在你将 TypeScript 深度用于实践工作之前,必须首先搞清楚为什么你要使用它,为什么要在项目中应用它;
- 如果它没能提高你的生产力,没能增强你正在构建的应用程序的可靠性,那么你就没有从中获得什么价值。
Keep learning…
以上是关于初探TypeScript的主要内容,如果未能解决你的问题,请参考以下文章