TypeScript学习

语法学习

**

  • let : 作用——声明变量,但声明的变量只能在let命令所在的代码块内有效。
  • eg:
for (let i = 0; i < 10; i++) {
  // ...
}

console.log(i);

但是定义的i只在for循环中生效。

TypeScript 中,使用 : 指定变量的类型,: 的前后有没有空格都可以。

let decLiteral: number = 6;

**

关于for循环的变量作用域:
var a = [];
for (let i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6](); // 输出结果为:6

上面代码中,变量i是let声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量,所以最后输出的是6。你可能会问,如果每一轮循环的变量i都是重新声明的,那它怎么知道上一轮循环的值,从而计算出本轮循环的值?这是因为 JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。

另外,for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。

for (let i = 0; i < 3; i++) {
  let i = 'abc';
  console.log(i);
}
// 输出结果为:
// abc
// abc
// abc

上面代码正确运行,输出了 3 次abc。这表明函数内部的变量i与循环变量i不在同一个作用域,有各自单独的作用域。

使用let定义变量,在变量定义之前调用变量,程序会报错.

暂时性死区

只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。

var tmp = 123;

if (true) {
  tmp = 'abc'; // ReferenceError
  let tmp;
}

上面代码中,存在全局变量tmp,但是块级作用域内let又声明了一个局部变量tmp,导致后者绑定这个块级作用域,所以在let声明变量前,对tmp赋值会报错。

不允许重复声明

let不允许在相同作用域内,重复声明同一个变量。

// 报错
function func() {
  let a = 10;
  var a = 1;
}

// 报错
function func() {
  let a = 10;
  let a = 1;
}

块级作用域

ES6 允许块级作用域的任意嵌套。

{{{{
  {let insane = 'Hello World'}
  console.log(insane); // 报错
}}}};

上面代码使用了一个五层的块级作用域,每一层都是一个单独的作用域。第四层作用域无法读取第五层作用域的内部变量。

const

const声明一个只读的常量。一旦声明,常量的值就不能改变。

const PI = 3.1415;
PI // 3.1415

PI = 3;
// TypeError: Assignment to constant variable.

const的作用域与let命令相同:只在声明所在的块级作用域内有效

数值定义§

使用 number 定义数值类型:

let decLiteral: number = 6;
let hexLiteral: number = 0xf00d;
// ES6 中的二进制表示法
let binaryLiteral: number = 0b1010;
// ES6 中的八进制表示法
let octalLiteral: number = 0o744;
let notANumber: number = NaN;
let infinityNumber: number = Infinity;

编译结果:

var decLiteral = 6;
var hexLiteral = 0xf00d;
// ES6 中的二进制表示法
var binaryLiteral = 10;
var octalLiteral = 484;
var notANumber = NaN;
var infinityNumber = Infinity;

字符串(模板类型)-------${myName}.(可以使用变量替换模板)

let myName: string = 'Tom';
let myAge: number = 25;

// 模板字符串
let sentence: string = `Hello, my name is ${myName}.
I'll be ${myAge + 1} years old next month.`;

空值§

在 TypeScript 中,可以用 void 表示没有任何返回值的函数:

function alertName(): void {
    alert('My name is Tom');
}

注意:undefined 和 null 是所有类型的子类型。也就是说 undefined 类型的变量,可以赋值给 number 类型的变量。

什么是任意值类型------any
any是任意值类型,被定义成any型的数据可以在后续过程中被替换成任意的数值。

任意值的属性和方法 在任意值上访问任何属性都是允许的:
let anyThing: any = 'hello';
console.log(anyThing.myName);
console.log(anyThing.myName.firstName);

也允许调用任何方法:

let anyThing: any = 'Tom';
anyThing.setName('Jerry');
anyThing.setName('Jerry').sayHello();
anyThing.myName.setFirstName('Cat');

可以认为,声明一个变量为任意值之后,对它的任何操作,返回的内容的类型都是任意值. 且当数据赋值时没有指出数据类型则默认为any类型

对象的类型——接口

什么叫做接口
(在面向对象语言中,接口(Interfaces)是一个很重要的概念,它对行为的抽象,而具体如何行动需要由类(classes)去实现(implemnt)。
TypeScript 中的接口是一个非常灵活的概念,除了可用于对类的一部分行为进行抽象以外,也常用于对「对象的形状(Shape)」进行描述。)

我们定义了一个接口 Person,接着定义了一个变量 tom,它的类型是 Person。这样,我们就约束了 tom 的形状必须和接口 Person 一致。
定义的变量比接口少了一些属性是不允许的,多了一些属性也是不允许的 赋值的时候,变量的形状必须和接口的形状保持一致。:

interface Person {
    name: string;
    age: number;
}

let tom: Person = {
    name: 'Tom'
};

如果我们希望变量和接口的形状可以存在差异那么我们就可以使用?变量名的形式定义变量:


interface Person {
    name: string;
    age?: number;
}

let tom: Person = {
    name: 'Tom'
};
  //age?: number;这种属性的形式被称为可选属性。

但是即使是可选属性可不可以增加属性-------为了解决此问题可以用 任意属性

interface Person {
    name: string;
    age?: number;
    [propName: string]: any; //可以接收多定义出来的属性。
    //使用 [propName: string] 定义了任意属性取 string 类型的值。

}

需要注意的是,一旦定义了任意属性,那么确定属性和可选属性的类型都必须是它的类型的子集:

let list: any[] = ['xcatliu', 25, { website: 'http://xcatliu.com' }];
//这种写法可以让数组中的元素是各种不同类型的。

有关函数问题

函数声明——函数在js中是至关重要的存在。

在 JavaScript 中,有两种常见的定义函数的方式——函数声明(Function Declaration)和函数表达式(Function Expression):

// 函数声明(Function Declaration)
function sum(x, y) {
    return x + y;
}

// 函数表达式(Function Expression)
let mySum = function (x, y) {
    return x + y;
};

在 TypeScript 的类型定义中,=> 用来表示函数的定义,左边是输入类型,需要用括号括起来,右边是输出类型。

let mySum: (x: number, y: number) => number = function (x: number, y: number): number {
    return x + y;
};
用接口定义函数的形状§

我们也可以使用接口的方式来定义一个函数需要符合的形状:

interface SearchFunc {
    (source: string, subString: string): boolean;
}

let mySearch: SearchFunc;
mySearch = function(source: string, subString: string) {
    return source.search(subString) !== -1;
}

采用函数表达式|接口定义函数的方式时,对等号左侧进行类型限制,可以保证以后对函数名赋值时保证参数个数、参数类型、返回值类型不变。

函数的定义

es5中定义方法{
定义方式:函数声明法
function run(){
    return "run";
}

定义方式:匿名函数
var run2 = function(){
    return "run2";
}
}

ts中函数定义方法{

function run(): string{
    return "run";
    // run是函数名,string是返回的数据类型;如果不知道返回类型是什么可以使用any,如果函数没有返回值可以使用viod。
}


定义方式:匿名函数
var run2 = function():{
    return "run2";
    
}

}

在函数调用的时候可以进行参数的传递,但是传递的参数必须指定类型。而且形参和实参数量需要一样,如果不一样需要在形参位置使用可选参数“变量名?:类型”eg k? : any
函数的重载:同样的函数传入不同的函数实现不同的方法。

箭头函数:

setTimeout(()=> { 
  alert('kk')
},1000)
//使用箭头函数时此时this的指向是上下文。
编译成js的代码————————————————————————————————————————————————
setTimeout(function () {
    alert('kk');
}, 1000);

js中类的定义(原型链):

function person(){
    this.name = "zhangsan"
    this.age = 21
    this.run = function(){
        console.log("名字是"+this.name)

    };
}

var p = new person();
p.run()

使用原型链给类添加属性或者方法,可以直接通过实例化对象调用。
ffunction person(){
    this.name = "zhangsan"
    this.age = 21
    this.run = function(){
        console.log("名字是"+this.name)

    };
}
person.getInfo=function(){/* getInfo是静态方法名*/
  console.log("这是一个静态方法可以直接通过类名.方法名进行使用")
}
person.getInfo()
person.prototype.xb = '男'
person.prototype.print= function(){
  console.log("性别是"+this.xb)
}
var p = new person();
p.run();
p.print();

继承的实现:对象冒充实现继承:没有办法继承到原型链上的方法:
function web()
{
//通过对像冒充实现继承
person.call(this);
}

function person(){
    this.name = "zhangsan"
    this.age = 21
    this.run = function(){
        console.log("名字是"+this.name)

    };
}
person.prototype.xb = '男'
person.prototype.print= function(){
  console.log("性别是"+this.xb)
}

function web(){
  person.call(this); //通过对像冒充实现继承
}

var w = new web()
w.run()//直接调用了person中的run方法  但是没有办法继承到原型链上的方法所以继承是不完整的 要想完整就要加上原型链继承:
web.prototype = new person()//实现原型链继承。

ts中实现类

class Porson { 
  private name: string; //属性,前面省略了public关键词
  constructor(name: string) {//构造函数  在实例化类的时候触发的函数方法
    this.name = name;
  }

  run(): any{
    return`${this.name}在运动`
   }

}
var p = new Porson("张三");
p.run();

class web extends Porson {//继承父类的属性和方法
  constructor(name: string) { 
    super(name)//把参数传到父类中
  }
}
var w = new web("小hehe");
w.run();

抽象类与抽象方法
pass

接口

在这里插入图片描述调用接口时传入的数值必须和接口定义的一样否则就会报错。

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}写代码`)
	}
}

var w = new Web('ruby')
w.eat()
w.work()

泛型

我们为了实现传参的自由性可以使用any定义参数类型,但是怎么做我们就放弃了类型检查的功能,即使传入的是字符型,返回的是数值型也不会报错,为了很好的解决这个问题我们使用泛型定义变量:其作用就是传入参数的类型和返回数值的类型必须一致。

function createArray<T>(length: number, value: T): Array<T> {
    let result: T[] = [];
    for (let i = 0; i < length; i++) {
        result[i] = value;
    }
    return result;
}

createArray<string>(3, 'x'); // ['x', 'x', 'x']
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值