TypeScript入门到精通——BigInt、展开原算符、解构、可选链运算符

BigInt

  如果在 JavaScript 程序中使用了较新的语言特性,那么这段 JavaScript 程序必须在支持该语言特性的运行环境中才能运行。但是,开发者通常无法决定 JavaScript 程序的实际运行环境,这就可能产生兼容性的问题。

  TypeScript 语言的一大特色就是能够支持 JavaScript 语言中的新特性而不必过多担心兼容问题。开发者可以在 TypeScript 程序中使用新的 JavaScript 语言特性,然后由编译器将程序编译成兼容指定 ECMAScript 规范版本的 JavaScript 程序。通过这种方式,开发者既可在程序中使用新的语言特性,又不必担心程序兼容性的问题。

一、BigInt

  BigInt 是在2019年9月被正式纳入 ECMAScript 标准中的特性。虽然 BigInt 不是频繁使用的特性,但其特殊性在于其它是一种新的原始数据类型,同时又属于数值类型的一种。由于 BigInt 类型的加入,JavaScript 中共支持两种数值类型,即 Number 类型和 BigInt 类型。

  目前,JavaScript 语言中共有以下七中原始数据类型:

    1. Undefined
    2. Null
    3. Boolean
    4. String
    5. Symbol
    6. Number
    7. BigInt

 JavaScript 语言使用双精度 64 位浮点数格式来表示 Number 类型的值。Number 类型能够安全表示的最大整数为 2^53 - 1,该数值能够使用内置的 Number 对象上的 MAX_SAFE_INTEGER 属性来表示。BigInt 类型能够表示任意精度的整数,尤其是大于 2^53 - 1 的整数,这也正是引入 BigInt 类型的原因。

1.1、创建 BigInt

  在 TypeScript 中,有两种方式可以创建 BigInt 类型的值:

1、使用BigInt()构造函数:可以使用BigInt()构造函数来创建一个BigInt类型的值。这个构造函数接受一个整数或字符串作为参数,并将其转换为BigInt类型。例如:

let bigNum = BigInt(12345678901234567890);  
console.log(bigNum); // 输出 12345678901234567890n

  在这个例子中,我们使用BigInt()构造函数来创建一个BigInt类型的值bigNum,并将其初始化为12345678901234567890

2、在整数后面加上n后缀:可以在整数后面加上n后缀来创建一个BigInt 类型的值。例如:

let bigNum = 12345678901234567890n;  
console.log(bigNum); // 输出 12345678901234567890n

  在这个例子中,我们在整数12345678901234567890 后面加上n后缀来创建一个BigInt类型的值bigNum

  需要注意的是,BigInt类型是一种特殊的整数类型,用于表示大于Number.MAX_SAFE_INTEGER(即 2^53 - 1)的整数。在 TypeScript 中,可以使用BigInt类型来处理超过这个范围的整数。在输出BigInt类型的值时,会在数值后面加上n后缀来表示其类型为BigInt。

1.2、BigInt与Number

  BigInt 类型的值能够与 Number 类型的值进行大小及相等关系的比较。在进行严格相等比较时,BigInt 类型的值与 Number 类型的值永远不相等。在进行非严格相等比较及大小关系比较时,BigInt 类型的值与 Number 类型的值进行数学意义上的比较。

  在 TypeScript 中,BigInt 和 Number 是两种不同的数值类型,用于表示不同范围的整数和浮点数。BigInt 类型是一种特殊的整数类型,用于表示大于Number.MAX_SAFE_INTEGER(即 2^53 - 1)的整数。在 TypeScript 中,可以使用 BigInt 类型来处理超过这个范围的整数。BigInt 类型的值在输出时会在数值后面加上n后缀来表示其类型为 BigInt。例如:

let bigNum = 12345678901234567890n;  
console.log(bigNum); // 输出 12345678901234567890n

  在这个例子中,我们创建了一个 BigInt 类型的值bigNum,并将其初始化为12345678901234567890。在输出时,bigNum的值为12345678901234567890n,表示其类型为 BigInt。

  Number 类型是 TypeScript 中表示浮点数的类型。它可以表示的范围是从-(2^53 - 1)2^53 - 1,包括整数和浮点数。在 TypeScript 中,可以使用 Number 类型来处理这个范围内的数值。例如:

let num = 3.14;  
console.log(num); // 输出 3.14 

  在这个例子中,我们创建了一个Number 类型的值num,并将其初始化为3.14。在输出时,num的值为3.14,表示其类型为Number。

  需要注意的是,由于 JavaScript和TypeScript中的 Number 类型都是使用 IEEE 754 标准来表示浮点数的,因此在处理浮点数时可能会遇到精度问题。例如,0.1+0.2的结果不是0.3,而是一个接近0.3的浮点数。这是由于浮点数的二进制表示无法精确表示某些十进制小数所导致的。如果需要更精确的小数计算,可以考虑使用库如 Decimal.js 或 Big.js。

展开运算符

二、展开运算符

  在 TypeScript 中,展开运算符(...)用于将一个数组或对象的属性展开到一个新的数组或对象中。它可以使代码更简洁和易读,同时提供了更灵活的方式来处理数组和对象。

  展开运算符可以用于以下场景: 

2.1、数组展开

  可以将一个数组的元素展开到一个新的数组中。例如:

 

let arr1 = [1, 2, 3];  
let arr2 = [...arr1, 4, 5];  
console.log(arr2); // 输出 [1, 2, 3, 4, 5]
  在这个例子中,我们使用展开运算符将 arr1 的元素展开到 arr2 中,并添加了新的元素 4 和 5。

2.2、对象展开

  可以将一个对象的属性展开到一个新的对象中。例如:

let obj1 = { a: 1, b: 2 };  
let obj2 = { ...obj1, c: 3 };  
console.log(obj2); // 输出 { a: 1, b: 2, c: 3 }

在这个例子中,我们使用展开运算符将 obj1 的属性展开到 obj2 中,并添加了新的属性 c。

2.3、函数展开

  可以将一个数组或对象的属性展开到函数的参数列表中。例如:

function greet(name, age) {  
  console.log(`Hello, ${name}! You are ${age} years old.`);  
}  
  
let person = { name: "Alice", age: 25 };  
greet(...person); // 输出 "Hello, Alice! You are 25 years old."

  在这个例子中,我们使用展开运算符将 person 对象的属性展开到 greet 函数的参数列表中,以便一次性传递多个参数。

  需要注意的是,展开运算符只能用于可迭代的对象(如数组或对象),并且无法直接用于原始值(如字符串、数字或布尔值)。如果要将原始值放入数组中,可以使用数组字面量语法。例如:let arr = [...new Set([1, 2, 3, 3])];。

解构

三、解构

  JavaScript 中的解构是指数组或对象在解构上进行分解,将其拆分成独立的子结构,然后可以访问那些拆分后的子结构。解构提供了一种更加便利的数据访问方式,使用解构语法能够极大地简化代码。

3.1、数组解构

  数组解构允许从数组中提取值并赋值给变量。在数组解构中,可以使用方括号[]来指定要从数组中提取的元素的顺序。例如:

let arr = [1, 2, 3];  
let [a, b, c] = arr;  
console.log(a); // 输出 1  
console.log(b); // 输出 2  
console.log(c); // 输出 3  

  在这个例子中,我们使用数组解构将 arr 数组中的元素分别赋值给变量 a、b 和 c。

  还可以使用剩余运算符(...)来提取数组中的剩余元素。例如:

let arr = [1, 2, 3, 4, 5];
let [a, b, ...c] = arr;
console.log(a); // 输出 1
console.log(b); // 输出 2
console.log(c); // 输出 [3, 4, 5]

  在这个例子中,我们使用数组解构将 arr 数组中的前两个元素分别赋值给变量 a 和 b,并使用剩余运算符将剩余的元素组成一个新数组赋值给变量 c。

3.2、对象解构

  对象解构允许从对象中提取属性并赋值给变量。在对象解构中,可以使用花括号 {} 来指定要从对象中提取的属性名称。例如:

let obj = { a: 1, b: 2, c: 3 };
let { a, b, c } = obj;
console.log(a); // 输出 1
console.log(b); // 输出 2
console.log(c); // 输出 3

  在这个例子中,我们使用对象解构将 obj 对象中的属性分别赋值给变量 a、b 和 c。

  还可以使用剩余运算符(...)来提取对象中的剩余属性。例如:

let obj = { a: 1, b: 2, c: 3, d: 4 };
let { a, b, ...c } = obj;
console.log(a); // 输出 1
console.log(b); // 输出 2
console.log(c); // 输出 { c: 3, d: 4 } 

  在这个例子中,我们使用对象解构将 obj 对象中的属性 a 和 b 分别赋值给变量 a 和 b,并使用剩余运算符将剩余的属性组成一个新对象赋值给变量 c。

  需要注意的是,在对象解构中,如果要从对象中提取的属性名称与已有的变量名称冲突,可以使用 as 关键字来重命名提取的属性。例如:

let obj = { a: 1, b: 2 };
let { a: x, b: y } = obj;
console.log(x); // 输出 1
console.log(y); // 输出 2

  在这个例子中,我们使用对象解构将 obj 对象中的属性 a 和 b 分别重命名为 x 和 y 并赋值给相应的变量。

可选链运算符

四、可选链运算符

  可选链运算符是 2019 年 12 月纳入 ECMAScript 标准中的新特性。TypeScript 3.7 版本增加了对可选链运算符的支持,因此我们可以在 TypeScript 3.7 及以上的版本直接使用该运算符。

  TypeScript 的可选链运算符(?.)是一种用于访问对象属性的简洁语法,它允许在访问属性链中的任何一个属性时,如果该属性不存在,则返回 undefined 而不是抛出错误。这在处理可能不存在的属性时非常有用,可以避免因访问未定义的属性而引发的运行时错误。

4.1、基础语法

  可选链运算符由一个问号和一个点号组成,即 "?."。可选链预算符有以下三种语法形式:

    • 可选的静态属性访问。
    • 可选的计算属性访问。
    • 可选的函数调用或方法调用。

4.1.1、可选的静态属性访问

  可选静态属性访问语法,如下所示:

obj?.prop

  在这个语法中,obj 是要访问属性的对象,prop 是要访问的属性名。如果 obj 是 undefined 或 null,则整个表达式返回 undefined。

举个例子:

class MyClass {  
  static prop = "Hello, world!";  
}  
  
console.log(MyClass?.prop); // 输出 "Hello, world!"

在这个例子中,我们使用可选链运算符访问了 MyClass 类的静态属性 prop。如果 MyClass 未定义,则整个表达式返回 undefined。 

4.1.2、可选的计算属性访问

  可选的计算属性访问语法,如下所示:

let obj = { a: 1, b: 2 };  
let propName = "a";  
  
console.log(obj?.[propName]); // 输出 1

在这个例子中,我们使用可选链运算符和计算属性访问了 obj 对象的 a 属性。如果 obj 未定义,则整个表达式返回 undefined。  

4.1.3、可选的函数调用或方法调用

  可选的函数调用或方法调用,如下所示:

let obj = { foo: () => "Hello, world!" };  
  
console.log(obj?.foo?()); // 输出 "Hello, world!"

在这个例子中,我们使用可选链运算符调用了 obj 对象的 foo 方法。如果 obj 未定义或 foo 方法不存在,则整个表达式返回 undefined。

4.2、短路求值

  可选链运算符采用了短路求值的策略,即在访问属性链中的任何一个属性时,如果该属性不存在,则整个表达式立即返回 undefined,而不会再继续访问后续的属性。这可以避免因访问未定义的属性而引发的运行时错误。

  当使用 TypeScript 的可选链运算符(?.)时,如果访问的属性链中的任何一个属性不存在,整个表达式将立即返回 undefined,而不会继续访问后续的属性。这就是所谓的短路求值。

  以下是一个示例,演示了如何使用可选链运算符和短路求值:

interface User {
name?: string;
age?: number;
address?: {
city?: string;
country?: string;
};
}

function getUserInfo(user: User) {
return `${user?.name} is ${user?.age} years old and lives in ${user?.address?.city}, ${user?.address?.country}.`;
}

const user1: User = { name: "Alice", age: 25 };
const user2: User = { name: "Bob" };
const user3: User = { name: "Charlie", address: { city: "New York" } };
const user4: User = { name: "David", address: { city: "London", country: "UK" } };
const user5: User = null;

console.log(getUserInfo(user1)); // 输出 "Alice is 25 years old and lives in undefined, undefined."
console.log(getUserInfo(user2)); // 输出 "Bob is undefined years old and lives in undefined, undefined."
console.log(getUserInfo(user3)); // 输出 "Charlie is undefined years old and lives in New York, undefined."
console.log(getUserInfo(user4)); // 输出 "David is undefined years old and lives in London, UK."
console.log(getUserInfo(user5)); // 输出 "undefined is undefined years old and lives in undefined, undefined."

  在这个示例中,我们定义了一个 User 接口,其中一些属性是可选的。然后,我们编写了一个 getUserInfo 函数,它使用可选链运算符来访问 User 对象中的属性。如果某个属性不存在,整个表达式将返回 undefined。

  通过短路求值的特性,我们可以在访问属性链时避免抛出错误。例如,在访问 user1 的 address 属性时,由于 address 属性不存在,因此后续的属性访问将不会执行,避免了因访问未定义的属性而引发的运行时错误。

4.3、空值合并运算符

  TypeScript 还引入了空值合并运算符(??),它用于在一个表达式的值为 null 或 undefined 时,提供一个备用值。这个运算符与可选链运算符结合使用时,可以在访问属性链时提供一个默认值,以避免返回 undefined。例如:

let obj = null;  
let value = obj?.prop ?? "default";  
console.log(value); // 输出 "default"

  在这个例子中,我们使用可选链运算符尝试访问 obj 对象的 prop 属性,但由于 obj 为 null,所以整个表达式返回 undefined。然后,我们使用空值合并运算符提供了一个默认值 "default",并将其赋值给 value 变量。最终输出结果为 "default"。

posted @ 2023-10-01 19:34  左扬  阅读(558)  评论(0编辑  收藏  举报
levels of contents