Skip to content

202306

INFO

6 月了,还不知道路在哪儿? 要做长久打算!

  • 20230522
  • 0602 不就是写一些伪代码吗 全背下来不就好了
  • 0607 已经坚持五天 继续坚持一个月
Details

默写平时可能用到的手写题

  • mockNew
  • apply/call/bind
  • compose
  • lru
  • 二分法
  • curry/curry2
  • deepclone
  • 无重复的最长子串
  • 反转链表
  • 删除链表某一个节点

0601

ts 练习 Subsequence

实现 Subsequence<T> 输出所有可能的子序列:

ts
type PP3 = Subsequence<[1, 2]>; // [] | [1] | [2] | [1, 2]
type Subsequence<T> = T extends [infer F, ...infer R extends number[]]
  ? Subsequence<R> | [F, ...Subsequence<R>]
  : T;
type PP4 = Subsequence<[1, 2, 3]>; // [] | [1, 2] | [2] | [1] | [1, 2, 3] | [2, 3] | [3] | [1, 3]

数组全排列 arr = [1,2,3]

js
function permute(arr) {
  var res = [];
  var len = arr.length;
  var backTrack = (arr, temp) => {
    res.push(temp.slice());
    for (let i = 0; i < len; i++) {
      if (!temp.includes(arr[i])) {
        temp.push(arr[i]);
        dfs(arr, temp);
        temp.pop();
      }
    }
  };
  backTrack(arr, []);
  return res;
}
permute([1, 2, 3]);

0602

  • 【代码题】 实现 compose 函数, 类似于 koa 的中间件洋葱模型
js
// 题目需求
let middleware = [];
middleware.push((next) => {
  console.log(next, "next");
  console.log(1);
  next();
  console.log(1.1);
});
middleware.push((next) => {
  console.log(2);
  next();
  console.log(2.1);
});
middleware.push((next) => {
  console.log(3);
  next();
  console.log(3.1);
});
function compose(arr) {
  return (next) => {
    return dispatch(0);
    function dispatch(i) {
      let fn = arr[i];
      if (!fn) return Promise.resolve();
      if (i === arr.length) fn = next;
      try {
        return Promise.resolve(fn(dispatch.bind(null, i + 1)));
      } catch (e) {
        return Promise.reject(e);
      }
    }
  };
}
let fn = compose(middleware);
fn();
// 1 2 3 3.1 2.1 1.1

举个例子

js
/**
 * Your LRUCache object will be instantiated and called as such:
 * var obj = new LRUCache(capacity)
 * var param_1 = obj.get(key)
 * obj.put(key,value)
 */
class LRU {
  constrcuor(num) {
    this.res = new Map();
    this.limit = num;
  }
  get(key) {
    // 如果存在 当前key滞后
    // 如果不存在 则返回-1
    if (this.res.has(key)) {
      var cur = this.res.get(key);
      this.res.delete(key);
      this.res.set(key, cur);
      return cur;
    } else {
      return -1;
    }
  }

  put(key, value) {
    // 如果没有直接设置
    var size = this.res.size;
    if (this.res.has(key)) {
      this.res.delete(key);
    } else {
      // 如果有的话 看总数
      if (this.limit <= size) {
        const oldKey = this.res.keys().next().value;
        this.res.delete(oldKey);
      }
    }
    this.res.set(key, value);
  }
}

TS 练习, PickByType

实现 PickByType<P, Q>,将对象 P 中类型为 Q 的 key 保留:

ts
type OnlyBoolean = PickByType<
  {
    name: string;
    count: number;
    isReadonly: boolean;
    isEnable: boolean;
  },
  boolean
>; // { isReadonly: boolean; isEnable: boolean; }
type PickByType<T extends Record<PropertyKey, any>, K> = {
  [U in keyof T as T[U] extends K ? U : never]: T[U];
};
type TT111 = { name: string; age: number };
type PP11 = Pick<TT111, "name">;
type PickTest<T extends Record<PropertyKey, any>, K extends keyof T> = {
  [P in K]: T[P];
};
type TT211 = PickTest<TT111, "name">;
  • 语录: 杨绛先生说:人在最艰难的时候,别老想着太远的将来,只要鼓励自己过好今天就好,这世界有太多的猝不及防,人生就是一场体验,请你尽兴。 岁月静好是片刻,一地鸡毛是日常,即使世界偶尔薄凉,内心也有繁花似锦,浅浅喜,静静爱,深深懂得,淡淡释怀,不去惊艳谁的人生,只温柔自己的岁月,落落大方,好好生活,望远处是风景,看近处才是人生,惟愿余生,岁月无恙,直言温暖,不语悲伤

杨绛先生说

0603

interviews

  • 如果不能继续向前学习,重拾以前也能打败 60%的,那就好好重拾以前!
  • 练习 Ts PartialByKeys

实现 PartialByKeys<T, K>,使 K 匹配的 Key 变成可选的定义,如果不传 K 效果与 Partial 一样:

ts
interface User {
  name: string;
  age: number;
  address: string;
}

type TT3 = Partial<User>;
type UserPartialName = PartialByKeys<User, "name">; // { name?:string; age:number; address:string }

type PartialByKeys<T, K = keyof T> = {
  [P in keyof T as P extends K ? P : never]?: T[P];
} & {
  [P in keyof T as P extends K ? never : P]: T[P];
} extends infer R
  ? {
      [P in keyof R]: R[P];
    }
  : never;

type HasIn<Arr, One> = Arr extends [infer F, ...infer R]
  ? Equal<One, F> extends true
    ? true
    : HasIn<R, One>
  : false;
type TT4 = HasIn<[1, 2, 3], 1>;

type Equal<A, B> = (<T>() => T extends A ? 1 : 2) extends <T>() => T extends B
  ? 1
  : 2
  ? true
  : false;
type TT5 = Equal<1, any>;

默写 compose

js
function compose(arr) {
  return (ctx, next) => {
    return dispatch(0);
    function dispatch(i) {
      var fn = arr[i];
      if (!fn) return Promise.resolve();
      if (i === arr.length) fn = next;
      try {
        return Promise.resolve(fn(ctx, () => dispatch(i + 1)));
      } catch (e) {
        return Promise.reject(e);
      }
    }
  };
}

默写 LRU

get/set

js
class LRU {
  constructor(num) {
    this.cache = new Map();
    this.limit = num;
  }
  get(key) {
    if (this.cache.has(key)) {
      const val = this.cache.get(key);
      this.cache.delete(key);
      this.cache.set(key, val);
      return val;
    }
    return -1;
  }
  set(key, val) {
    if (this.cache.has(key)) {
      this.cache.delete(key);
    } else {
      // 需要删除头部的key
      // 删除的前提是池子满了
      if (this.limit <= this.cache.size) {
        var oldKey = this.cache.keys().next().value;
        this.cache.delete(oldKey);
      }
    }
    this.cache.set(key, val);
  }
}

默写反转链表

js
function reverse(head) {
  let cur = head;
  let pre = null;
  while (cur) {
    var next = cur.next;
    cur.next = pre;
    pre = cur;
    cur = next;
  }
  return pre;
}

0604

做饭做了四个小时,

0605

访问页面 -> nginx -> 网关 -> 微服务

请求:Browser -> nginx -> 网关 -> node -> webqiji 返回: webqiji(Data) -> node(HTML) -> 网关 -> nginx -> Browser

  • ts 练习 1 实现函数 PromiseAll,输入 PromiseLike,输出 Promise<T>,其中 T 是输入的解析结果:
ts
const promiseAllTest1 = PromiseAll([1, 2, 3] as const);
const promiseAllTest2 = PromiseAll([1, 2, Promise.resolve(3)] as const);
const promiseAllTest3 = PromiseAll([1, 2, Promise.resolve(3)]);

declare function PromiseAll<T>(values: T): Promise<{
  [K in keyof T]: T[K] extends Promise<infer U> ? U : T[K];
}>;
  • ts 练习 2 Type Lookup 实现 LookUp<T, P>,从联合类型 T 中查找 type 为 P 的项并返回: LookUp<T, P>
ts
interface Cat {
  type: "cat";
  breeds: "Abyssinian" | "Shorthair" | "Curl" | "Bengal";
}

interface Dog {
  type: "dog";
  breeds: "Hound" | "Brittany" | "Bulldog" | "Boxer";
  color: "brown" | "white" | "black";
}

type MyDog = LookUp<Cat | Dog, "dog">; // expected to be `Dog`

type LookUp<T, P> = T extends {
  type: infer U;
}
  ? U extends P
    ? T
    : never
  : never;
type LookUp2<U extends { type: any }, T extends U["type"]> = U extends {
  type: T;
}
  ? U
  : never;

type MyDog2 = LookUp2<Cat | Dog, "dog">;
  • 手写 js 基础 - new 手写
js
function Person(name) {
  this.name = name;
}
function mockNew(fn, ...rest) {
  // 创建一个对象
  // 新对象的原型属性proto指向构造函数的 prototype 属性
  // 执行该方法
  // 如果是对象则返回 如果不是对象则需要返回一个对象
  var target = Object.create(fn.prototype);
  var res = fn.apply(target, rest);
  return res instanceof Object ? res : target;
}

var tt1 = new Person("cpp");
var tt2 = mockNew(Person, "cpp");
  • 手写 apply 和 call
js
function sayName(name) {
  console.log(name, 'fn inner')
  return name
}
sayName.call(null, 'wmh')
function mockApply(obj, ...rest) {
  obj = Object(obj); || window
  var symbol = Symbol()
  obj[symbol] = this
  var res = obj[symbol](...rest)
  delete obj[symbol]
  return res
}

手写无重复的最长子串

js
/**
 * @param {string} s
 * @return {number}
 */
var lengthOfLongestSubstring = function (s) {
  if (!s || s.length === 0) return 0;
  let max = 0;
  let temp = [];
  for (let i = 0; i < s.length; i++) {
    var index = s.indexOf(s[i]);
    if (index > -1) {
      arr.splice(0, i + 1);
    }
    arr.push(s[i]);
    max = Math.max(max, arr.length);
  }
  return max;
};

0606

  • 函数柯里化
js
// 参数固定
function curry(fn) {
  var judge = (...arg) => {
    if (fn.length === arg.length) {
      return fn(...arg);
    }
    return (...args) => judge(...args, ...arg);
  };
  return judge;
}
var sum = (a, b, c) => a + b + c;
var map = curry(sum);
map(1)(2)(3);

// 参数不固定
function curry2(fn) {
  var arr = [];
  return function temp(...arg) {
    if (arg.length) {
      arr.push(...arg);
      return temp;
    } else {
      var res = fn.apply(this, arr);
      arr = [];
      return res;
    }
  };
}
var sum1 = (...rest) => rest.reduce((a, b) => a + b, 0);
var map1 = curry2(sum1);
map1(1)(2)(3)();
  • 练习 TS-Trim

实现 Trim<T>,将字符串左侧或者右侧空格清空:

ts
type trimed = TrimLeft<"  Hello World  ">; // expected to be 'Hello World
type TrimLeft<T extends string> = T extends `${infer A} ` ? TrimLeft<A> : T;
type TR1 = TrimLeft<" cpp ">;
type Trim<T extends string> = T extends `${infer A} ` | ` ${infer A}`
  ? Trim<A>
  : T;
type TR2 = Trim<" cpp ">;
  • 练习 TS Capitalize 实现 Capitalize<T> 将字符串第一个字母大写:
ts
type capitalized = Capitalize1<"hello world">; // expected to be 'Hello world'
type Capitalize1<T extends string> = T extends `${infer F}${infer Z}`
  ? `${Uppercase<F>}${Z}`
  : T;
type TR3 = Capitalize<"hello world">;
  • 除了勤加练习基本功,还需要熟知常用的八股文,简历上写的 react/vite/rollup

0607

  • 2023 年高考第一天,13 年前我参加 2010 年高考,现在回想如果能回去,中考就要好好考,考到县中,大环境很重要,即使在县中倒数也比现在的学校强,其次就是选科,选物化生,理科满级
  • 看了年轻人得了癌症的帖子,今日健康来之不易,平时生活习惯很重要,要懂得珍惜
  • 手写 bind
js
Function.prototype.myBind = function (context) {
  var self = this;
  var arg = Array.prototype.slice.call(arguments, 1);
  var Bridge = function () {};
  var fBind = () => {
    var args = Array.from(arguments);
    self.apply(this instanceof self ? this : context, [...args, ...arg]);
  };
  Bridge.prototype = this.prototype;
  fBind.prototype = new Brideg();
  return fBind;
};

function myName(name, age) {
  return "cpp";
}
var obj = {
  val: 1,
};
var test1 = myName.bind(obj, "wmh");
test1(30);
  • 根据节点值删除该节点
js
/**
 * @param {ListNode} head
 * @param {number} val
 * @return {ListNode}
 */
var deleteNode = function (head, val) {
  let dummy = {
    val: 0,
    next: head,
  };
  let cur = dummy;
  while (cur.next) {
    if (cur.next.val === val) {
      cur.next = cur.next.next;
      break;
    }
    cur = cur.next;
  }
  return dummy.next;
};
var test = {
  val: 1,
  next: {
    val: 2,
    next: {
      val: 3,
      next: {
        val: 4,
        next: {
          val: 5,
          next: undefined,
        },
      },
    },
  },
};
deleteNode(test, 3);
  • 链表中是否有环
js
// 快慢指针
/**
 * @param {ListNode} head
 * @return {boolean}
 */
var hasCycle = function (head) {
  var slow = head;
  var fase = head;
  while (fast && fast.next) {
    slow = slow.next;
    fast = fast.next.next;
    if (slow === fast) {
      return true;
    }
  }
  return false;
};
// hash表
var hasCycle = function (head) {
  var m = new Map();
  while (head) {
    if (m.has(head)) {
      return true;
    }
    m.set(head, true);
    head = head.next();
  }
  return false;
};
  • 找出链表中环的入口节点
js
/**
 * @param {ListNode} head
 * @return {ListNode}
 * 哈希表存遍历过的节点,每遍历一个节点,都查看哈希表是否存在当前节点,如果存在,则说明链表有环
如果不存在,则存入哈希表,继续遍历
时间复杂度为 O(n),空间复杂度为 O(n)

 */
var detectCycle = function (head) {
  var m = new Map();
  var cur = head;
  while (cur) {
    if (m.has(cur)) {
      return cur;
    }
    m.set(cur, cur);
    cur = cur.next;
  }
  return null;
};

0608

  • 如何私有 sourcemap 服务?

  • 按照现在的水平,退休金不会超过 2000 块,如果想达到 3000 块,还能得继续缴 12 年, 得保持现在到 2035 年

  • 今天刷 maimai,看到一条说说

  • SEO 优化相关

  • 不断操练手写题,没啥意义,唯一的意义就是下次在背书的时候,拾起的速度越来越快,越来越快!!

  • 继续默写手写 js 基础题

js
// 何以解忧 唯有手写代码
// 大数相加
function stringAdd(a, b) {
  var len = Math.max(a.length, b.length);
  a = a.padStart(len, 0);
  b = b.padStart(len, 0);
  let res = "";
  let flag = 0;
  for (let i = len - 1; i >= 0; i--) {
    flag = Number(a[i]) + Number(b[i]) + flag;
    res = (flag % 10) + res;
    flag = Math.floor(flag / 10);
  }
  res = flag === 1 ? "1" + res : res;
  return res;
}
stringAdd("1234", "78901");
  • 练习 ts 手写
ts
type Fn = (a: number, b: string) => number;

type Result = AppendArgument<Fn, boolean>;
// expected be (a: number, b: string, x: boolean) => number
type AppendArgument<F, E> = F extends (...arg: infer T) => infer R
  ? (...arg: [...T, E]) => R
  : F;
  • 实现 TS 版函数 Replace<S, From, To>,将字符串 From 替换为 To:
ts
type replaced = Replace<"types are fun!", "fun", "awesome">; // expected to be 'types are awesome!'

type Replace<S, F, T extends string> = S extends `${infer FF}${F}${infer R}`
  ? `${FF}${T}${R}`
  : S;
  • 实现基本的ReturnType
ts
function sayName2(value: number, age: number): number;
function sayName2(value: string): string | undefined;
function sayName2(
  value: string | number,
  age: number = 0
): string | number | undefined {
  if (typeof value === "number") {
    return age;
  } else {
    return value;
  }
}
// sayName2("1111"); // ok
// sayName2(10, 10); // ok
type TPP1 = ReturnType<typeof sayName2>;
type MockReturnType<T extends (...arg: any) => any> = T extends (
  arg: any
) => infer R
  ? R
  : never;
type TPP2 = MockReturnType<typeof sayName2>;
  • 实现基本的Parameters
ts
type TP2 = Parameters<typeof sayName2>;
type MockParamters<T extends (...arg: any) => any> = T extends (
  ...arg: infer P
) => any
  ? P
  : never;
type TP3 = MockParamters<typeof sayName2>;

0609

  • js 手写
js
// 16进制跟rgb进行转换
// #fffff => rgb(255, 255, 255)
function hexToRgb(str) {
  var r, g, b;
  var rgb = str.replace("#", "0x");
  r = rgb >> 16;
  g = (rgb >> 8) & 0xff;
  b = rgb & 0xff;
  return `rgb(${r}, ${g}, ${b})`;
}

// rgb转十六进制
// rgb(255, 255, 255) => #ffffff
function rgbToHex(str) {
  const [a, r, g, b] = str.split(/[^\d]+/);
  const toHex = (num) => {
    const hex = (+num).toString(16);
    return hex.length === 1 ? `0${hex}` : hex;
  };
  return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
}
rgbToHex("rgb(255,255,255)");

0610

  • 手写 js 函数名连接符大小写
js
// cpp_wmh => cppWmh
function toRewrite(str) {}
  • 手写 js 中的模拟 map/filter/reduce
js
Array.prototype.myMap = function (fn, context) {
  var arr = Array.prototype.call(this) || [];
  var res = [];
  for (let i = 0; i < arr.length; i++) {
    res.push(fn.call(context, arr[i], i, arr));
  }
  return res;
};
var res = [1, 2, 3];
res.map((e) => e * 2);
res.myMap((e) => e * 2);
js
Array.prototype.myReduce = function (fn, init) {};

0611-0614

写业务

0615-0618

苏州拍婚纱

0619

  • 手写 reduce
js
Array.prototype.myReduce = function (fn, init) {
  const arr = Array.prototype.slice.call(this) || [];
  let res = init ? init : arr[0];
  for (let i = init ? 0 : 1; i < arr.length; i++) {
    res = fn.call(null, res, arr[i], i, arr);
  }
  return res;
};

var test = [12, 23, 45];
var test2 = test.reduce((a, b) => a + b, 10);
console.log(test2);
  • 手写原生 ajax
js
function dealAjax(fn, url) {}
  • 打乱数组
js
const shuffle = (arr) => {
  return arr.sort((e) => {
    return Math.random() > 0.5 ? 1 : -1;
  });
};
shuffle([2, 33, 11, 2222, 9]);
  • 管道函数
js
function fn1(x) {
  console.log(11);
  return x + 1;
}

function fn2(x) {
  return x + 2;
}

function fn3(x) {
  return x + 3;
}

function fn4(x) {
  console.log(44);
  return x + 4;
}
// 从右往左
const compose = (...fns) => {
  if (fns.length === 0) return (num) => num;
  if (fns.length === 1) return fns[0];
  return fns.reduce((pre, next) => {
    return (...num) => {
      return pre(next(...num));
    };
  });
};
var all = compose(fn1, fn2, fn3, fn4);
all(10);
// 从左往右
const pipe = function () {
  // 从左往右执行函数组合
  const args = [].slice.apply(arguments);
  return function (value) {
    return args.reduce((acc, fn) => fn(acc), value);
  };
};
var double = (x) => x * 2;
var triple = (x) => x * 3;
var quadruple = (x) => x * 4;
var fn = pipe1(double, triple, quadruple);
var fn1 = pipe(double, triple, quadruple);
fn1(2);

0620

  • 随时都有被时代淘汰的可能,随时要做好准备
  • 继续操练手写 js
js
// 发布订阅模式
class EventEmitter {}

// 数组扁平化
function flatten(arr) {
  var stack = [...arr];
  var res = [];
  while (stack.length) {
    var cur = stack.pop();
    if (Array.isArray(cur)) {
      stack.push(...cur);
    } else {
      res.push(cur);
    }
  }
  return res.reverse();
}

var test = [
  [1, 2, 3],
  [2, [3, 4, 5]],
];
console.log(flatten(test));

Array.prototype.myFlat = function (num) {};

0621

  • 业务上兼容 IE 浏览器,蛋疼
  • 明天回家,准备下

0622/23/24

连云港老家过端午 尽管很想呆在老家,考虑到现实情况,很难

0625

  • 继续搬砖
  • 大学专业研究下,切记一定是建议,建议,建议,仅供参考,仅供参考,仅供参考,毕竟不是自己去学,也不要替人做决定
  • 7 月 1 号去体检,所以最近几天不能超过 12 点睡觉

0626/0627

  • 业务上修改 bug

0628

  • 找到自己的热爱,这个问题很复杂,不见得一下就有答案,如果还没有找到,请不要放弃
  • 什么事都要留有余地,尤其当今,不要亮出自己底牌
  • 对方家里的事一概不要提
  • 默写 mockReduce
js
Array.prototype.myReduce = function (fn, init) {
  const arr = Array.prototype.slice.call(this) || [];
  let res = init ? init : arr[0];
  for (let i = init ? 0 : 1; i < arr.length; i++) {
    res = fn.call(null, res, arr[i], i, arr);
  }
  return res;
};

0629

  • 计算数组中每个元素出现的次数
js
function countEvery(arr) {
  let max = 0;
  const obj = arr.reduce((acc, cur) => {
    if (!(cur in acc)) {
      acc[cur] = 1;
    } else {
      acc[cur] += 1;
      max = Math.max(max, acc[cur]);
    }
    return acc;
  }, {});
  return max;
}
var arr = ["cpp", "wmh", "cpp", "chen", "chen", "chen"];
var test = countEvery(arr);
console.log(test);

0630

  • 来公司的第 750 天,走过了三分之一,还有三分之二的历程
  • 又是彷徨的一天,希望自己能振作起来。又到一年一度的复职的日子,回首半年,不知道核心在哪里