TypeScript 初探(一)

3

什么是 TypeScript

它是JavaScript的一个超集(微软开发的自由和开源的编程语言)。
(等等,超集是什么?)如下图:
图片描述

为什么选择 TypeScript

  1. Angular2.x 开始用TypeScript语言来开发(如果你要用这个框架)

  2. TypeScript 非常包容 .js 文件可以直接重命名为 .ts

  3. 静态语言、强类型语言的TypeScript
    这里得先了解一下几个名词:动态语言静态语言强类型语言弱类型语言

动态语言:动态语言是指在运行期间才去做数据类型检查的语言,也就是说,在用动态类型的语言编程时,永远也不用给任何变量指定数据类型,该语言会在你第一次赋值给变量时,在内部将数据类型记录下来。

静态语言:静态语言与动态类型语言刚好相反,它的数据类型是在编译其间检的,也就是说在写程序时要声明所有变量的数据类型.

强类型定义语言:强制数据类型定义的语言。也就是说,一旦一个变量被指定了某个数据类型,如果不经过强制转换,那么它就永远是这个数据类型了。

弱类型定义语言:数据类型可以被忽略的语言。它与强类型定义语言相反, 一个变量可以赋不同数据类型的值。

遇到的问题
用动态语言、弱类型语言的JavaScript开发时,运行js之前,想确认下数据的类型用的是否正确,变量有没有重复定义,相互覆盖难等等,这些正确性判断基本得靠人为来了,出错的可能性那当然高了,而且对人的高求高呀。

解决问题:
那是否考虑下换一种开发方式呢? 用一种类似静态语言,强类型语言的开发方式来进行javascript的开发会更好一点呢? 有的那就是TypeScript。

TypeScript的使用

变量声明(let ,const)

首先我们先来看下这个例子:

for (var i = 0; i < 10; i++) {
    setTimeout(function() { console.log(i); }, 100 * i);
}
//结果  10 10 10 10 10 10 10 10 10 10 10

for (let i = 0; i < 10 ; i++) {
    setTimeout(function() {console.log(i); }, 100 * i);
}
//结果  0 1 2 3 4 5 6 7 8 9 

特点:

  1. 块级作用域

    function f(input: boolean) {
    let a = 100;
    if (input) {
        let b = a + 1;
        return b;
    }
    return b;  // Error: 'b' doesn't exist here
    }
  2. 不能在被声明之前定义

    a++; // illegal to use 'a' before it's declared;let a;
    
  3. 重定义及屏蔽

    function sumMatrix( {
    let sum = 0;
    for (let i = 0; i < matrix.length; i++) {
        var currentRow = matrix[i];
        for (let i = 0; i < currentRow.length; i++) {
            sum += currentRow[i];
        }
    }
    return sum;
    }

const 与let声明相似,变量被赋值后不能再改变。

    const foo = {
      a: 1
    }
    foo.a = 2; 值会变吗?

let 与 var 的异同点比较
图片描述


枚举(enum)

概念:在程序设计语言中,一般用一个数值来代表某一状态,这种处理方法不直观,易读性差。如果能在程序中用自然语言中有相应含义的单词来代表某一状态,则程序就很容易阅读和理解。也就是说,事先考虑到某一变量可能取的值,尽量用自然语言中含义清楚的单词来表示它的每一个值,这种方法称为枚举方法,用这种方法定义的类型称枚举类型。

  • 例子:

    enum Direction {
        Left  = 37,  //向上的按键代码是37,用Direction.up通俗易懂的名词来描述
        Up,
        Right,
        Down         
    }

    ts==========>js

    var Direction;
    (function (Direction) {
      Direction[Direction["Left"] = 37] = "Left";
      Direction[Direction["Up"] = 38] = "Up";
      Direction[Direction["Right"] = 39] = "Right";
      Direction[Direction["Down"] = 40] = "Down";
    })(Direction || (Direction = {}));
    

解构

解构赋值允许你使用类似数组或对象字面量的语法将数组和对象的属性赋给各种变量。这种赋值语法极度简洁,同时还比传统的属性访问方法更为清晰。

通常来说,你很可能这样访问数组中的前三个元素:

var first = someArray[0];
var second = someArray[1];
var third = someArray[2];

如果使用解构赋值的特性,将会使等效的代码变得更加简洁并且可读性更高:

var[first, second, third]= someArray;

常用于:数组,对象

函数

箭头函数

箭头函数在简单的函数使用中更为简洁直观。

1. const fn = () => {...}
2. const fn = foo => `${foo} world `      模版字符串  
3. const fn = (foo, bar) => foo + bar
4. const fn = (foo,bar) => {…}

this 穿透: 函数内部的this延伸至上一层作用域中。

let obj = {
    hello: 'world',
    foo() {
        let bar = () => this.hello;
        return bar
    }
}

不能随意在顶层作用域使用箭头函数

let obj = {
    hello: 'world',
    foo:() => this.hello;
}

函数重载

函数根据传入不同的参数而返回不同类型的数据

function pickCard(x: {suit: string; card: number; }[]): number;

function pickCard(x: number): {suit: string; card: number; };

function pickCard(x): any {}

TypeScript基于类的面向对象的开发方式。谈到面向对象就会谈到它的三大特性是:封装,继承,多态 。
这里讨论一下多态:

多态:同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。在运行时,可以通过指向基类的指针,来调用实现派生类中的方法。
把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化。

举个例子:

class Animal {
        constructor(){}
        call() {}
}

class Dog extends Animal {
    constructor() {
        super();
    }
    call() {
        console.log("wangwang");
    }
}
class Cat extends Animal {
    constructor() {
        super();
    }
    call() {
        console.log("miaomiao");
    }
}
let tom: Animal = new Dog();    
tom.call();    //tom 是Animal类型,但是它调用 Dog的call方法

类有3个成员:

  1. 属性

  2. 构造函数

  3. 方法。

继承

extends关键字

class Animal {
    name:string;
    constructor(theName: string) { this.name = theName; }
}
class Snake extends Animal {
    constructor(name: string) { super(name); }
}

包含构造函数的派生类必须调用super(),它会执行基类的构造方法

public,private,protected 修饰符

public :公共(默认)
private:不能在声明它的类的外部访问(包括派生类)
protected:protected修饰符与private修饰符的行为很相似,但有一点不同,protected成员在派生类中仍然可以访问.

存取器getters/setters

目的:对象成员的读取操作。

只带有get不带有set的存取器自动被推断为readonly。

class Employee {
    private _fullName: string;

    get fullName(): string {
        return this._fullName;
    }

    set fullName(newName: string) {
        if (passcode && passcode == "secret passcode") {
            this._fullName = newName;
        }
        else {
            console.log("Error: Unauthorized update of employee!");
        }
    }
}

静态属性

这些属性存在于类本身上面而不是类的实例上。

class Grid {
    static origin = {x: 0, y: 0};
    constructor () { }
}

ts================>js

var Grid = (function () {
    function Grid() {
    }
    return Grid;
}());
Grid.origin = { x: 0, y: 0 };

抽象类

抽象类做为其它派生类的基类使用。 它们一般不会直接被实例化。 不同于接口,抽象类可以包含成员的实现细节。 abstract关键字是用于定义抽象类和在抽象类内部定义抽象方法。

abstract class Animal {
    abstract makeSound(): void;
    move(): void {
        console.log('roaming the earch...');
    }
}

你可能感兴趣的

载入中...