TypeScript入门到精通——TypeScript语言基础

TypeScript 语言基础

  TypeScript 是 JavaScript 的超集。更确切的说,TypeScript 是 ECMAScript 2015(ES6)的超集。

  TypeScript 语言支持 ECMAScript 2015 规范中定义的所有特性,例如类和模块等。JavaScript 程序本身就是合法的 TypeScript 程序。JavaScript 语言中的所有语法均可以在 TypeScript 语言中使用并且具有完全相同的语义。

1、变量

  在计算机程序中,一个变量使用给定的符号名与内存中的某个存储地址相关联并且可以容纳某个值。变量的值可以在程序的执行过程中改变。当我们操作变量时,实际上操作的是变量对应的存储地址中的数据。因此,在程序中可以使用变量来存储和操作数据。

1.1、变量特性

  Javascript 中的变量是松散类型的,可以保存任何类型的数据。由于不存在定义某个变量必须要保存何种数据类型值的规则,变量的值及其数据类型可以在脚本的生命周期内改变 

1.2、变量名

定义:在 JavaScript 中,每个变量都有唯一的名字,也叫作标识符。

变量可以任意取名,但必须遵循命名规则:

    1. 允许包含字母、数字、下划线和美元符号"$"。
    2. 字符中的字母可以包括拓展的 ASCII 或 Unicode 字母字符,也可以使用中文。
    3. 仅允许使用字母、Unicode 转义序列、下划线和美元符号($)作为第一个字符,不允许使用数字作为第一个字符。
    4. 不能使用关键字、保留字、true、false和null。
    5. 标识符区分大小写。
    6. 当标识符中需要多个单词进行表示时,常见的表示放式有下划线法(user_name)、驼峰法(userName)和帕斯卡法(UserName)。

保留关键字:

保留关键字是指在 JavaScript 语言中被事先定义好并赋予特殊含义的单词,不能作为变量名和函数名使用,以下列举的是 ES5 中规定的一些关键字:

ES5 中的关键字

break,case,catch,class, const,continue

debugger,default,delete, do, else,export

extends, false,finally,for ,function,if

import, in,instanceof, new,null, return

super,switch,this,throw, try, true

typeof,var, void,while, with, yield

未来保留关键字

abstract,arguments,await,byte,boolen,char

double,enum,eval,final ,float, goto

implements, int ,interface, let ,long,native

package,private,protected,public,short ,static

synchronized,throws,transient,volatile

1.3、变量声明

 在 JavaScript 中有三种声明变量的方式,它们分别使用以下关键字:

  其中,var 声明是在 ECMAScript 2015 之前就已经支持的变量声明方式,而 let 和 const 声明则是在 ECMAScript 2015 中新引入的变量声明方式。在很多编程语言中都提供了对块级作用域的支持,它能够帮助开发者避免一些错误。

  使用 let 和 const 关键字能够声明具有块级作用域的变量,这弥补了 var 声明的不足。因此推荐在程序中使用 let 和 const 声明来代替 var 声明。

 1.3.1、var 声明

  var声明使用 var 关键字来定义。在声明变量时,可以为变量赋予一个初始值。若变量未初始化,则其默认值为 undefined。示例如下:

var x = 0;

var y; // undefined

    1.3.2、let 声明

  let声明使用let关键字来定义。在声明变量时,可以为变量赋予一个初始值。若变量未初始化,则其默认值为 undefined。示例如下:

let x = 0;

let y; //undefined

    1.3.3、const 声明

  与 var 声明和 let 声明不同,const 声明用于定义一个常量。const 声明使用 const 关键字来定义,并且在定义时必须设置一个初始值。const 声明在初始化之后不允许重新赋值。示例如下:

const x = 0;

    1.3.3、const 块级作用域

  块级作用域的概念包含了两部分,即块和作用域。变量的作用域指的是该变量的可访问区域,一个变量只能在其所处的作用域内被访问,在作用域外是不可见的。

  块级作用域中的块指的是 "块语句"。块语句用于将零条或多条语句组织在一起。在语法上,块语句使用一对大括号 "{}" 来表示。

  块级作用域指的是块语句所创建的作用域,使用 let 声明和 const 声明的变量具有块级作用域,但是使用 var 声明的变量不具有块级作用域。

2、注释

2.1、单行注释

单行注释使用双斜线 "//" 来表示,并且不允许换行。

//这里是双斜线注释
const  x=0;

2.2、多行注释

多行注释以 "/*" 符号作为开始,并以 "*/"结束。

/** 这里是多行注释 **/
const x=0;


/**
  这里是多行注释,
  多行注释允许换行。
**/
const y=0;

2.3、区域注释

//#region      这里定义了代码折叠区域起始的位置。

let x=0;

//#endregion   这里定义了代码折叠区域的结束位置。

3.3、数据类型

计算机程序是通过操作值来进行运行的,数据类型是值的一个属性,它能够描述在该值上允许执行的操作。

在 ECMAScript 2015 规范中定义了如下七中数据类型:

    • Undefined:只包含一个值,即 undefined。在变量未被初始化时,它的值为 undefined。
    • Null:只包含一个值,即 Null。我们通常使用 null 值来表示未初始化的对象。此外,null 值也常被用在 JSON 文件中,表示一个值不存在。
    • Boolean:包含两个逻辑值,分别是 true 和 false。
    • String:表示文本字符串,它由 0 个或多个字符构成。JavaScript 使用 UTF-16 编码来表示一个字符。
    • Symbol:是 ECMAScript 2015 新引入的原始类型。Symbol 值有一个重要特征,那就是每一个 Symbol 值都是唯一的且不可改变的。Symbol 值的主要应用场景是作为对象的属性名。
    • Number:表示一个数字。
    • Object:对象是属性的结合,每个对象属性都属于以下两种形式之一:
      • 数据属性:可以为 Undefined、Null、Boolean、String、Number、Symbol 和 Object类型的值。
      • 存取器属性:由一个或两个存取器方法构成,用于获取和设置 Undefined、Null、Boolean、String、Number、Symbol和Object类型的值。

3.4、字面量

  在计算机科学中,字面量用于在源代码中表示某个固定值。在 JavaScript 程序中,字面量不是变量,它是直接给出的固定值。

在 TypeScript 中,字面量是指在代码中直接表示值的数据。TypeScript 支持多种类型的字面量,包括:

    1. 数字字面量:使用数字表示的值,例如 423.14
    2. 字符串字面量:使用单引号或双引号包围的文本值,例如 'Hello, world!'"TypeScript is awesome!"
    3. 布尔字面量:表示真或假的值,即 true 或 false
    4. 空值字面量:表示空或不存在的值,使用关键字 null
    5. 未定义值字面量:表示未定义的值,使用关键字 undefined
    6. 符号字面量:使用 Symbol() 函数创建的唯一值,例如 const sym = Symbol('my symbol');

  除了这些基本的字面量类型,TypeScript 还支持其他类型的字面量,如数组字面量、对象字面量、模板字面量等。这些字面量类型允许你在代码中直接创建和操作相应的数据结构。

// 数字字面量
const num: number = 42;

// 字符串字面量
const str: string = 'Hello, world!';

// 布尔字面量
const isTrue: boolean = true;

// 空值字面量
const n: null = null;

// 未定义值字面量
let u: undefined;

// 符号字面量
const sym: symbol = Symbol('my symbol');

// 数组字面量
const arr: number[] = [1, 2, 3, 4, 5];

// 对象字面量
const obj: { name: string; age: number } = { name: 'Alice', age: 25 };

// 模板字面量
const greeting: string = `Hello, ${obj.name}!`;

3.5、对象

  在 JavaScript 中,对象属于非原始类型。同时,对象也是一种复合数据类型,它由若干个对象属性构成。对象属性可以是任意数据类型,如数字、函数或者对象等。当对象属性为函数时,我们通常称之为方法。当然,这只是惯用叫法不同,在本质上并无差别。

进一步分析其中的意思: 这段话主要描述了 JavaScript 中的对象及其属性。以下是对这段话的详细分析:

1、对象属于非原始类型:在 JavaScript 中,数据类型可以分为原始类型(Primitive types)和非原始类型(Non-primitive types)。原始类型包括 Number、String、Boolean、Null、Undefined 和 Symbol,它们是基本的数据类型,不能再被进一步分解。而非原始类型,也就是对象类型(Object types),它们是由原始类型或者其他对象类型组合而成的复杂数据类型,例如 Object、Array、Function 等。

2、对象是一种复合数据类型:复合数据类型是由其他数据类型组合而成的数据类型。在 JavaScript 中,对象是一种复合数据类型,它可以包含多个属性。

3、对象属性可以是任意数据类型:对象的属性可以是任何数据类型,包括原始类型如 Number、String、Boolean,也可以是其他对象类型如 Object、Array、Function 等。这意味着我们可以创建一个包含各种不同类型数据的对象。

4、当对象属性为函数时,我们通常称之为方法:在 JavaScript 中,如果对象的属性是一个函数,我们通常把这个属性称为方法。方法和普通的对象属性本质上是一样的,都是对象的一部分,只是它们的值是函数。方法可以被调用,执行特定的操作,这是它们和普通属性的主要区别。

总的来说,这段话描述了 JavaScript 中的对象及其属性的特性和用法。对象是 JavaScript 中非常重要的数据类型,它们提供了组织和处理数据的强大方式。

在  TypeScript 方法与 JavaScript 方法、Go 方法、Python 方法,有什么不同?

我理解的意思:TypeScript、JavaScript、Go和Python都是流行的编程语言,它们各自的方法有一些相似性和差异性。下面是对这些语言方法的简要比较:

1、TypeScript 方法: TypeScript 是 JavaScript 的一个超集,添加了静态类型和其他特性。TypeScript 的方法与 JavaScript 的方法非常相似,可以使用类和对象来定义。TypeScript 还引入了接口和泛型等概念,使得方法的定义更加灵活和类型安全。

2、JavaScript 方法: JavaScript 是一种动态类型的脚本语言,其方法可以通过对象和类来定义。JavaScript 的方法可以使用 function 关键字或者箭头函数来定义,并且可以通过对象的属性来访问。

3、Go 方法: Go 是一种静态类型的编译型语言,其方法只能通过类型来定义。Go 的方法使用 func 关键字来定义,并且必须显式地指定接收者(receiver),接收者是一个类型实例,表示该方法属于该类型。Go 的方法可以通过值接收者或者指针接收者来定义,这影响了方法内部对接收者的访问方式。

4、Python 方法: Python 是一种动态类型的解释型语言,其方法可以通过类和对象来定义。Python 的方法使用 def 关键字来定义,并且可以使用对象的属性来访问。Python 还支持静态方法和类方法,它们分别通过 @staticmethod 和 @classmethod 装饰器来定义。

总结: TypeScript 和 JavaScript 的方法非常相似,可以通过对象和类来定义,但 TypeScript 提供了更多的类型安全和灵活性。 Go 的方法只能通过类型来定义,并且必须显式地指定接收者。 Python 的方法可以通过类和对象来定义,支持静态方法和类方法。

3.5.1、对象字面量

  对象字面量也叫作对象初始化器,是最常用的创建对象的方法。

3.5.1.2、数据属性

  对象字面量的数据属性由属性名和属性值组成,语法如下所示:

let obj = {
  property1: value1,
  property2: value2,
  ...
};

  在上面的语法中,property1、property2 等是属性的名称,value1、value2 等是属性的值。这些属性名和属性值构成了对象的数据属性。

3.5.1.2、存取器属性

  在 TypeScript 中,对象字面量还支持存取器属性。一个存取器属性由一个get方法和/或一个set方法组成。get方法用于获取属性的值,而set方法用于设置属性的值。

let obj = {
  _privateValue: 10, // 私有属性,外部无法直接访问
  get publicValue() { // get 方法,用于获取属性的值
    return this._privateValue;
  },
  set publicValue(value) { // set 方法,用于设置属性的值
    this._privateValue = value;
  }
};

console.log(obj.publicValue); // 输出 10
obj.publicValue = 20; // 设置属性值
console.log(obj.publicValue); // 输出 20

在上面的示例中,obj对象有一个私有属性_privateValue和一个存取器属性publicValuepublicValue有一个get方法和一个set方法,分别用于获取和设置_privateValue的值。外部代码无法直接访问_privateValue,但可以通过publicValue来间接访问和修改它。

3.5.1.3、可计算属性名

  在 TypeScript 中,可以使用表达式作为属性名来定义对象字面量属性,这被称为可计算属性名。表达式的结果将被用作属性的名称。

let obj = {};
let propName = 'myProp';
let propValue = 'Hello, world!';

// 使用可计算属性名动态地添加属性
obj = {
  [propName]: propValue,
  get [propName]() {
    return this[propName];
  },
  set [propName](value) {
    this[propName] = value;
  }
};

console.log(obj.myProp); // 输出 'Hello, world!'

// 使用 getter 和 setter 方法来访问和修改属性
console.log(obj['myProp']); // 输出 'Hello, world!'
obj['myProp'] = 'Hello, TypeScript!';
console.log(obj.myProp); // 输出 'Hello, TypeScript!'

  在上面的示例中,我们使用了可计算属性名来动态地创建了一个对象obj,并添加了一个属性myProp。属性的值被初始化为'Hello, world!'。我们还定义了一个getter方法和一个setter方法,分别用于获取和设置属性的值。在getter和setter方法中,我们使用了this[propName]来访问和修改属性的值。最后,我们通过obj.myPropobj['myProp']来访问和修改了这个动态添加的属性,并输出了它的值。

3.5.2、原型对象

  每个对象都有一个原型。对象的原型既可以是一个对象,即原型对象,也可以是 null值。原型对象又有其自身的原型,因此对象的原型会形成一条原型链,原型链将终止于 null 值。原型对象本质上是一个普通对象,用于在不同对象之间共享属性和方法。对象与其原型之间具有隐含的引用关系。

  在 TypeScript 中,对象的原型与 JavaScript 中的原型概念相似。每个对象都有一个原型,它是一个用于继承属性和方法的对象。对象的原型可以通过Object.getPrototypeOf()方法来获取,也可以通过obj.__proto__属性来访问(尽管__proto__属性是非标准的,但在大多数现代浏览器中仍然可用)。

class Person {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
  greet() {
    console.log(`Hello, my name is ${this.name}.`);
  }
}

let person = new Person('Alice');

// 访问对象的原型
let proto = Object.getPrototypeOf(person);
console.log(proto); // 输出 Person 类的原型对象

// 访问原型对象的属性和方法
console.log(proto.constructor); // 输出 Person 类
proto.greet(); // 输出 "Hello, my name is Alice."

// 检查对象的原型链
console.log(Object.getPrototypeOf(proto)); // 输出 Object 类的原型对象
console.log(Object.getPrototypeOf(Object.getPrototypeOf(proto))); // 输出 null

  在上面的示例中,我们定义了一个Person类,并创建了一个person对象。通过Object.getPrototypeOf()方法,我们可以获取person对象的原型,也就是Person类的原型对象。然后,我们可以访问该原型对象的属性和方法,如constructor属性和greet()方法。最后,我们还检查了对象的原型链,可以看到它最终终止于null值。

  需要注意的是,TypeScript 中的类和接口提供了一种更结构化的方式来定义对象和继承,而不直接使用原型。然而,了解原型和原型链的概念仍然对于理解 TypeScript 和 JavaScript 中的对象模型非常重要。

3.6、数组

  在 TypeScript 中,数组是一种特殊的对象,用于存储有序的元素集合。数组的元素可以是任意类型,包括数字、字符串、对象、函数等。下面是关于 TypeScript 数组定义、数组字面量和数组元素的详细介绍。

3.6.1、数组定义

  在 TypeScript 中,可以使用数组类型来定义数组。数组类型使用方括号[]表示,在方括号中指定元素的类型。例如,要定义一个包含字符串的数组,可以使用以下语法:

let arr: string[] = [];

  在这个例子中,arr是一个字符串类型的数组,初始化为空数组。

3.6.2、数组字面量

  数组字面量是一种快速创建数组的方式,使用方括号[]来表示。可以在方括号中列出数组的元素,用逗号分隔。例如,要创建一个包含数字 1、2、3 的数组,可以使用以下语法:

let arr = [1, 2, 3];

  在这个例子中,arr是一个包含三个数字的数组。

3.6.3、数组中的元素

  数组中的元素可以是任意类型,包括原始类型(如数字、字符串)和对象类型(如对象、数组、函数)。在 TypeScript 中,可以使用索引来访问数组中的元素。索引是从 0 开始的数字,表示元素在数组中的位置。例如,要访问上面创建的数组arr中的第一个元素,可以使用以下语法:

let firstElement = arr[0];
console.log(firstElement); // 输出 1

  在这个例子中,我们使用索引 0 来访问arr数组中的第一个元素,并将其赋值给变量firstElement。然后,我们将该元素输出到控制台。

  需要注意的是,在 TypeScript 中,数组的索引可以是任意类型,但通常是数字。此外,TypeScript 还提供了一些数组的方法和属性,用于操作和管理数组,例如push()pop()length 等。

  在 TypeScript 、JavaScript、Go、Python、Java、Shell 数组,有什么不同?

我理解的意思:在 TypeScript、JavaScript、Go、Python、Java 和 Shell 中,数组的概念和用法有很多相似之处,但也存在一些差异。以下是它们之间的主要差异:

1、TypeScript 和 JavaScript: TypeScript 是 JavaScript 的一个超集,引入了静态类型系统和一些其他特性。在数组方面,TypeScript 提供了更强大的类型检查,可以在定义数组时指定元素的类型。而 JavaScript 则是一种动态类型语言,数组可以包含任意类型的元素。

2、Go 和 Python: Go 和 Python 都支持数组,但在长度可变性方面有所不同。Go 中的数组长度是固定的,一旦创建就无法更改。而 Python 中的数组(称为列表)长度是可变的,可以随时添加或删除元素。

3、Java: Java 中的数组是一种对象,可以包含基本数据类型或对象类型。Java 还提供了一些数组相关的类和接口,如 Arrays 和 Collection,用于操作和管理数组。

4、Shell: Shell 脚本语言中的数组与其他编程语言有所不同,shell 数组是固定的,一旦创建就无法更改,无法直接添加或删除元素。Shell 中的数组可以包含任意类型的元素,包括字符串和数字。Shell 还提供了一些特殊的数组变量和操作符,用于访问和操作数组元素。

3.7、函数

  函数是程序必不可少的组成部分之一,它允许我们创建可重用的代码单元。我们通常会将具有独立功能的代码提取成函数以提高代码的可重用性与可测试行。

  JavaScript 中的函数是 "头等函数",它具有以下特性:

    • 函数可以赋值给变量或对象属性。
    • 函数可以作为参数传递给另外一个函数。
    • 函数可以作为函数返回值。

  因为支持头等函数,所以 JavaScript 也在一定程度上支持函数式编程范式。

3.7.1、函数声明

  在 TypeScript 中,函数声明是一种定义函数的方式,用于指定函数的名称、参数列表和返回类型。函数声明不会立即创建函数,而是在代码执行时创建一个函数对象。下面是 TypeScript 函数声明的详细介绍和示例:

 

function functionName(parameters): returnType {  
  // 函数体  
}
    1. function 关键字:用于声明一个函数。
    2. functionName:函数的名称,用于标识和调用函数。
    3. parameters:函数的参数列表,用逗号分隔。每个参数由参数名和参数类型组成。
    4. returnType:函数的返回类型,表示函数执行完成后返回值的类型。
    5. 函数体:包含实现函数功能的代码块。

  下面是一个简单的 TypeScript 函数声明的示例:

function greet(name: string): string {  
  return `Hello, ${name}!`;  
}  

  在这个例子中,我们声明了一个名为greet的函数,它接受一个字符串类型的参数name,并返回一个字符串类型的值。函数体内使用模板字符串将参数name插入到问候语中,并返回结果。

  函数声明的组成部分:

    1. function关键字:用于声明一个函数。
    2. 函数名:用于标识和调用函数。
    3. 参数列表:用逗号分隔的参数列表,每个参数由参数名和参数类型组成。
    4. 返回类型:表示函数执行完成后返回值的类型。
    5. 函数体:包含实现函数功能的代码块。

  需要注意的是,在TypeScript中,函数也可以作为值来使用,可以赋值给变量或作为对象的方法。此外,TypeScript还支持函数重载,允许定义多个具有不同参数列表和返回类型的函数,以提供更灵活的函数使用方式。

3.7.2、函数表达式

  除了函数声明外,还可以使用函数表达式来定义一个函数。函数表达式的语法与函数声明的语法有一个重要区别,那就是函数表达式中的函数名是可选的。当没有指定函数名时,该函数也叫作匿名函数。

  下面是一个使用函数表达式定义函数的 TypeScript 示例:

let greet = function(name: string): string {  
  return `Hello, ${name}!`;  
};  

console.log(greet("Alice")); // 输出 "Hello, Alice!" 

  在这个例子中,我们使用函数表达式定义了一个名为greet的函数,并将其赋值给一个变量。这个函数接受一个字符串类型的参数name,并返回一个字符串类型的值。与函数声明不同,函数表达式中的函数名是可选的,因此这个函数也可以被称为匿名函数。我们随后使用console.log()方法来调用这个函数,并输出结果。

3.7.3、箭头函数

  箭头函数是 ECMAScript 2015 中新增的特性,用来定义匿名的函数表达式。在TypeScript中,箭头函数是一种更简洁的函数表达方式,使用箭头=>来表示函数的参数和函数体。箭头函数在语法上比传统的函数表达式更简洁,并且有一些特殊的特性。

 下面是 TypeScript 箭头函数的详细介绍:

(parameters) => expression

  或者:

(parameters) => { statements }
    1. parameters:箭头函数的参数列表,用逗号分隔。每个参数由参数名和参数类型组成。如果没有参数,可以使用空括号()
    2. =>:箭头符号,用于连接参数列表和函数体。
    3. expression:箭头函数的返回值,可以是一个表达式或者一个值。如果函数体只有一个表达式,可以省略大括号{ }return关键字。
    4. { statements }:箭头函数的函数体,包含一个或多个语句。如果函数体有多条语句,需要使用大括号{ }包裹起来。

  下面是一个简单的 TypeScript 箭头函数的示例:

let greet = (name: string) => `Hello, ${name}!`;  
  
console.log(greet("Alice")); // 输出 "Hello, Alice!"  
  箭头函数除了能够提供简洁的语法外还有一个特别重要的特性,那就是箭头函数本身没有 this 绑定,它使用外层作用域中的 this 绑定。该特性能够帮助缓解程序中常见的一些错误。
posted @ 2023-10-01 12:59  左扬  阅读(77)  评论(0编辑  收藏  举报
levels of contents