每日的知识积累,包括 1 个 Ts 类型体操,两个 Leetcode 算法题,三个前端八股文题,四个英语表达积累。
1. 一个类型体操
题目
假如我们有一个 Promise 对象,这个 Promise 对象会返回一个类型。在 TS 中,我们用 Promise 中的 T 来描述这个 Promise 返回的类型。请你实现一个类型,可以获取这个类型。
例如:Promise,请你返回 ExampleType 类型。
type ExampleType = Promise<string>
type ExampleType2 = Promise<Promise<string>>
type Result = MyAwaited<ExampleType> // string
type Result2 = MyAwaited<ExampleType2> // string
分析
这个并没有看起来那么难,就是普通的 extends 和 infer 的使用,只不过加了递归而已。
尝试写出
type MyAwaited<T extends Promise<unknown>> = T extends Promise<infer U> ? (U extends Promise<unknown> ? MyAwaited<U> : U) : never;
测试用例
type ExampleType = Promise<string>
type ExampleType2 = Promise<Promise<number>>
type Result = MyAwaited<ExampleType> // string
type Result2 = MyAwaited<ExampleType2> // number
参考答案
type MyAwaited<T extends Promise<unknown>> = T extends Promise<infer U> ? (U extends Promise<unknown> ? MyAwaited<U> : U) : never;
经验总结
只能说和标准答案一模一样,但是还是要注意 unknown 的使用场景。
2. 两个 Leetcode 题目
刷题的顺序参考这篇文章 LeeCode 刷题顺序
2.1 [448] 找到数组中消失的数字
给你一个含 n 个整数的数组 nums ,其中 nums[i] 在区间 [1, n] 内。请你找出所有在 [1, n] 范围内但没有出现在 nums 中的数字,并以数组的形式返回结果。
示例 1:
输入:nums = [4,3,2,7,8,2,3,1]
输出:[5,6]
示例 2:
输入:nums = [1,1]
输出:[2]
提示:
n == nums.length
1 <= n <= 105
1 <= nums[i] <= n
进阶:你能在不使用额外空间且时间复杂度为 O(n) 的情况下解决这个问题吗? 你可以假定返回的数组不算在额外空间内。
尝试实现:
/**
* @param {number[]} nums
* @return {number[]}
*/
var findDisappearedNumbers = function(nums) {
let length = nums.length;
const rst = [];
for(let i = 0; i < length; i++) {
const _i = Math.abs(nums[i])-1;
const num = nums[_i];
if(num>0) nums[_i] = -num;
}
for(let i = 0; i < length; i++) {
const num = nums[i];
if(num > 0) rst.push(i+1);
}
return rst;
};
我的思路:
- 遍历数组,由于从 1 开始并且为正整数,且最大值不会超过 n
- 那么就可以使用绝对值表示原来的数值信息,使用正负表示是否出现的信息
- 对于每一个遍历到的元素 i,取绝对值减 1 表示一个下表,通过此下标找到原数组中的对应元素,如果此元素为负数则表示 i 已经重复出现了,如果为正数则将原来的值写成相反数
- 第二次遍历找到所有依然为正数的下标加 1 即可
得分结果: 81.25% 75.57%
经验总结: 少些了一个 Math.abs
2.2 [442] 数组中重复的元素
给你一个长度为 n 的整数数组 nums ,其中 nums 的所有整数都在范围 [1, n] 内,且每个整数出现 一次 或 两次 。请你找出所有出现 两次 的整数,并以数组形式返回。
你必须设计并实现一个时间复杂度为 O(n) 且仅使用常量额外空间(不包括存储输出所需的空间)的算法解决此问题。
示例 1:
输入:nums = [4,3,2,7,8,2,3,1]
输出:[2,3]
示例 2:
输入:nums = [1,1,2]
输出:[1]
示例 3:
输入:nums = [1]
输出:[]
提示:
n == nums.length
1 <= n <= 105
1 <= nums[i] <= n
nums 中的每个元素出现 一次 或 两次.
尝试完成:
/**
* @param {number[]} nums
* @return {number[]}
*/
var findDuplicates = function(nums) {
const rst = [];
const length = nums.length;
for(let i = 0; i < length; i++) {
const _i = Math.abs(nums[i]) - 1;
const num = nums[_i];
if(num > 0) {
nums[_i] = -num;
} else {
rst.push(Math.abs(nums[i]));
};
}
return rst;
};
我的思路: 考虑到数组元素组成的特殊性,可以用原来元素的绝对值表示数据信息,而使用正负表示重复信息。
得分结果: 89.34% 65.48%
经验总结: 函数最后忘记输出 rst.
3. 三个前端题目
- 如何获取安全的 undefined 的值? 在回答这个问题之前,先看一些事实:
- 如果在浏览器中运行
const undefined = 20;则浏览器报错:Identifier 'undefined' has already been declared'; 而如果运行的是:const null = 20;浏览器报错为:unexpected token 'null'; - 也就是说对于浏览器来说 undefined 只是一个普通的 identifier 而不是 token;也就是说** undefined 是标识符而不是保留字**!
- 这一点在 node 环境中表现的更加的透彻:
let undefined = 20;
console.log(undefined); // 20
- 所以 undefined作 为标识符其值是有被篡改的风险的。在实际中一般使用
void 0 或者 void(0)表示 undefined 的含义,因为这个表达式的返回值恒为此。
- typeof NaN 的结果是什么?
先说结论,返回值为:
'number'注意这里的字符串和小写。
NaN 有几个特性,一个是不和自身相等;第二个是在 Object.is 中又是相等的;第三个是表示的语义为: not a number
- isNaN 和 Number.isNaN 的区别是什么?
- 两者表示完全不同的语义,是完全不相同的两个方法!
- isNaN(x) 是在判断
x is not a number的正确性; - 而 Number.isNaN(x) 是在判断
x is NaN的正确性;
-
对于 isNaN(x) 来说,只要 x 不是一个 num 就会返回 true,反之返回 false。(注意这里我用的是num,也就是一种独特的东西,和 number 类型不是一回事)
那么,isNaN 对于 x 的判定规则是什么呢?其实非常简单,首先 x 如果值为 NaN,则 isNaN 认为 x 不是一个 num;其次,如果 x 不为 NaN,但却是 number 类型,则 isNaN 认为 x 是一个 num;最后,倘若 x 不是 number 类型的,isNaN 会尝试将 x 转成 number 类型(这种转化不同于 Number(x) 的强制类型转化,是内部机制),而转化的结果有三种:①NaN,②报错,③其他;
如果是第一种则 isNaN 认为 x 不是 num,如果是第三种,isNaN 认为 x 是 num。什么时候会出现情况 ② 呢,如果 x 的类型是 bigint 或者 symbol 就会使 isNaN 报错。
-
对于 Number.isNaN(x) 来说,情况就简单的多了,只要 x 不是 NaN 就返回 false,否则返回 true.
这里补充js中的哪些计算会返回 NaN 来:
- NaN
- Number.NaN
- 'abc' - 1
- 0 / 0
- Math.aqrt(-1)
- Number({})
- Number('abc')
4.四句英语积累
- go round(the table) -- to ask ideas
- Let me just [go around the table] and get everyone's opion on this.
- Can we go around the table and take a vote?
- finalise -- to finish the last part
- Will we be able to [finalise the deal] this week?
- Maria, can you please [finalise the arrangements for our trip to Mumbai]?