每日知识积累 Day 4

171 阅读5分钟

每日的知识积累,包括 1 个 Ts 类型体操,两个 Leetcode 算法题,三个前端八股文题,四个英语表达积累。

1. 一个类型体操

类型体操题目集合

Awaited

题目

假如我们有一个 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. 遍历数组,由于从 1 开始并且为正整数,且最大值不会超过 n
  2. 那么就可以使用绝对值表示原来的数值信息,使用正负表示是否出现的信息
  3. 对于每一个遍历到的元素 i,取绝对值减 1 表示一个下表,通过此下标找到原数组中的对应元素,如果此元素为负数则表示 i 已经重复出现了,如果为正数则将原来的值写成相反数
  4. 第二次遍历找到所有依然为正数的下标加 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. 三个前端题目

  1. 如何获取安全的 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 的含义,因为这个表达式的返回值恒为此。
  1. typeof NaN 的结果是什么? 先说结论,返回值为:'number' 注意这里的字符串和小写。

NaN 有几个特性,一个是不和自身相等;第二个是在 Object.is 中又是相等的;第三个是表示的语义为: not a number

  1. isNaN 和 Number.isNaN 的区别是什么?
  • 两者表示完全不同的语义,是完全不相同的两个方法!
  • isNaN(x) 是在判断 x is not a number 的正确性;
  • 而 Number.isNaN(x) 是在判断 x is NaN 的正确性;
  1. 对于 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 报错。

  2. 对于 Number.isNaN(x) 来说,情况就简单的多了,只要 x 不是 NaN 就返回 false,否则返回 true.

这里补充js中的哪些计算会返回 NaN 来:

  • NaN
  • Number.NaN
  • 'abc' - 1
  • 0 / 0
  • Math.aqrt(-1)
  • Number({})
  • Number('abc')

4.四句英语积累

  1. 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?
  2. 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]?