先来回顾一下上期的问题及答案:
1. 手写一个深拷贝
深拷贝是指创建一个新对象,将原始对象的所有属性递归地复制到新对象中,包括嵌套对象和数组。以下是一个手写深拷贝的示例代码:
function deepClone(obj: any): any {
if (obj === null || typeof obj !== 'object') {
return obj; // 非对象或 null 直接返回
}
let clone: any;
if (Array.isArray(obj)) {
clone = [];
for (let i = 0; i < obj.length; i++) {
clone[i] = deepClone(obj[i]); // 递归复制数组元素
}
} else {
clone = {};
for (const key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
clone[key] = deepClone(obj[key]); // 递归复制对象属性
}
}
}
return clone;
}
上述代码通过递归的方式实现了深拷贝,可以处理对象和数组的情况,保证了每个属性的值都是独立的。
2. 讲解 Promise.all
、Promise.race
、Promise.allSettled
的相同与不同
这三个方法都是 JavaScript 中用于处理 Promise 的方法,下面对它们进行详细解释:
Promise.all
:接收一个 Promise 数组作为参数,并返回一个新的 Promise。只有当所有的 Promise 都变为 resolved 状态时,新的 Promise 才会变为 resolved 状态,返回值是一个包含所有 Promise 结果的数组。如果其中一个 Promise 变为 rejected 状态,新的 Promise 就会立即变为 rejected 状态。
const promise1 = Promise.resolve(1);
const promise2 = Promise.resolve(2);
const promise3 = Promise.resolve(3);
Promise.all([promise1, promise2, promise3])
.then((results) => {
console.log(results); // 输出:[1, 2, 3]
})
.catch((error) => {
console.error(error);
});
Promise.race
:接收一个 Promise 数组作为参数,并返回一个新的 Promise。只要其中一个 Promise 变为 resolved 或 rejected 状态,新的 Promise 就会立即变为相同的状态,并返回相应的值。
const promise1 = new Promise((resolve) => setTimeout(resolve, 1000, 'one'));
const promise2 = new Promise((resolve) => setTimeout(resolve, 2000, 'two'));
Promise.race([promise1, promise2])
.then((result) => {
console.log(result); // 输出:'one'
})
.catch((error) => {
console.error(error);
});
Promise.allSettled
:接收一个 Promise 数组作为参数,并返回一个新的 Promise。无论 Promise 是 resolved 还是 rejected,新的 Promise 都会变为 resolved 状态,返回值是一个包含每个 Promise 结果的对象数组,每个对象包含status
和value
属性,表示 Promise 的状态和结果。
const promise1 = Promise.resolve(1);
const promise
2 = Promise.reject('error');
Promise.allSettled([promise1, promise2])
.then((results) => {
console.log(results);
// 输出:
// [
// { status: 'fulfilled', value: 1 },
// { status: 'rejected', reason: 'error' }
// ]
})
.catch((error) => {
console.error(error);
});
相同点:
都是用于处理 Promise 的方法,接收一个 Promise 数组作为参数。
返回一个新的 Promise 对象。
不同点:
Promise.all
要求所有 Promise 都变为 resolved 状态才会返回结果,一旦其中一个 Promise 变为 rejected 状态,整个 Promise 就会立即变为 rejected 状态。Promise.race
只要其中一个 Promise 变为 resolved 或 rejected 状态,整个 Promise 就会立即返回相应的结果。Promise.allSettled
不管 Promise 是 resolved 还是 rejected,都会返回结果,每个 Promise 的状态和结果都会被记录下来。
3. TypeScript 中的 unknown
类型应用场景
unknown
是 TypeScript 中的顶级类型,它表示一个未知类型的值。与 any
类型不同,unknown
类型是类型安全的,不能直接访问其属性或调用其方法,除非经过类型断言或类型保护。unknown
类型的应用场景包括:
动态数据解析:当需要处理从外部源(如 API 响应或用户输入)获取的数据时,通常无法事先确定其结构和类型,此时可以将其标记为
unknown
类型,并使用类型断言或类型保护来处理数据的解析。
function parseData(data: unknown): void {
if (typeof data === 'string') {
console.log(data.toUpperCase());
} else if (Array.isArray(data)) {
console.log(data.length);
} else {
console.log('Unknown data type');
}
}
parseData('hello'); // 输出:HELLO
parseData([1, 2, 3]); // 输出:3
parseData({}); // 输出:Unknown data type
存储动态类型数据:当需要存储可以是多种类型的数据时,可以使用
unknown
类型来灵活处理。
let dynamicData: unknown;
dynamicData = 'hello';
console.log(typeof dynamicData); // 输出:string
dynamicData = 123;
console.log(typeof dynamicData); // 输出:number
dynamicData = true;
console.log(typeof dynamicData); // 输出:boolean
异常情况处理:当处理可能引发异常或未知错误的操作时,可以使用
unknown
类型来捕获异常,并提供适当的错误处理机制。
try {
// 可能会抛出异常的操作
} catch (error: unknown) {
console.error('An error occurred:', error);
}
总之,unknown
类型在 TypeScript 中用于表示未知类型的值,适用于需要处理动态数据、存储动态类型数据或处理异常情况的场景。使用 unknown
类型可以提
供更好的类型安全性和编码规范性。
2023年6月28日
问题:什么是 TypeScript?它与 JavaScript 有什么区别?请列举 TypeScript 的一些特性和优势。
问题:什么是类型断言(Type Assertion)?请解释类型断言的作用和用法,并提供一个示例。
问题:什么是泛型(Generics)?请解释泛型的概念和用途,并给出一个使用泛型的例子。
上面问题的答案会在第二天的公众号推文中公布,大家可以关注公众号:程序员每日三问,第一时间获得推送内容。
学习不打烊,充电加油只为遇到更好的自己,每天早上9点纯手工发布面试题(死磕自己,愉悦大家) 希望大家在这浮夸的程序员圈里保持冷静,每天坚持花20分钟来学习与思考,在千变万化,类库层出不穷的今天,不要等到找工作时才狂刷题,提倡每日学习。