202312
INFO
马上又年长了 1 岁,可技术没有与之递增,要有紧促感!
20231101
焦急等待开奖,还不知道路在哪里 2023118
20231126 攻克算法
20231201 react 框架需要重塑
1201
简单来说, Server Actions 可以直接让我们在 JSX 代码中操作 Server 相关的能力。
- 你的问题主要在于读书不多而想得太多。——杨绛
1202
- 906,1 月 935 2 月 966 3 月 995 4 月 1026,后续戛然而止
- react 和打包工具八股文整理,背诵
- 阿里前端 p7 面试实战,附答案
RAIL(response/animation/idle/load)
RAIL 是一个关于浏览器性能优化的指导原则,它提供了一种系统化的方法来评估和改善网页应用的性能。RAIL 是由 Google 提出的,旨在帮助开发人员更好地理解和优化用户体验。 RAIL 模型的核心理念是将用户的交互操作分解为四个关键阶段:
响应(Response):在 100 毫秒以内响应用户的输入,使用户感觉到立即的反馈。这包括处理点击、滚动和触摸等用户交互。
动画(Animation):保持动画流畅并以每秒 60 帧的速度进行渲染,以确保动画的平滑度和视觉连续性。
空闲(Idle):利用主线程空闲时间执行后台任务,例如预加载资源、数据获取和计算等,以避免阻塞用户交互。
加载(Load):在 5 秒内将页面内容加载完毕,并在此期间提供关键内容,以使用户能够尽快与页面进行交互。
RAIL 模型的目标是在每个阶段都提供良好的用户体验,并确保在关键性能指标上达到可接受的水平。通过使用 RAIL,开发人员可以更有针对性地优化网页应用的性能,提高用户满意度。 需要注意的是,RAIL 模型并不是一种具体的技术或工具,而是一种方法论和指导原则,它可以与其他性能优化技术和工具结合使用,帮助开发人员构建高性能的网页应用。
1203
- 907,前端面试几大块:算法/项目/框架 生态/八股文,目前几个缺点,算法题刷的不够多,框架八股文总结的不够好,需要多总结,多背背 算法和框架两个大子项如何短时间内进步呢?
做好重复记忆和多次训练以及思维导图
1204
908,时间飞逝,准备已接近一个月,准备还没达到 60%
JSX 语法和 template 语法区别
- JSX 具有 JavaScript 的完整表现力,可以构建非常复杂的组件。但是灵活的语法,也意味着引擎难以理解,无法预判开发者的用户意图,从而难以优化性能。
2.Template 模板是一种非常有约束的语言,你只能以某种方式去编写模板。
- Vue3.0 动静结合的 DOM diff
Vue3.0 提出动静结合的 DOM diff 思想,动静结合的 DOM diff 其实是在预编译阶段进行了优化。之所以能够做到预编译优化,是因为 Vue core 可以静态分析 template,在解析模版时,整个 parse 的过程是利用正则表达式顺序解析模板,当解析到开始标签、闭合标签和文本的时候都会分别执行对应的回调函数,来达到构造 AST 树的目的。
借助预编译过程,Vue 可以做到的预编译优化就很强大了。比如在预编译时标记出模版中可能变化的组件节点,再次进行渲染前 diff 时就可以跳过“永远不会变化的节点”,而只需要对比“可能会变化的动态节点”。这也就是动静结合的 DOM diff 将 diff 成本与模版大小正相关优化到与动态节点正相关的理论依据。
1205
- 909
- 每天做题,刷题,刷到 2 月份(刷到 1 月底就算是成功了一半),争取把常见的/热门的/常考的背好,真正让你写的时候,不慌,即使有一点没写对,慢慢调试,都是没问题的。量化:时间刷到 2 月份,算法刷到 100 题
- 题目永远刷不完,我深知这一点,所以应该有个觉悟,把核心知识点掌握,理解透,下次再来复习时,理解的速度会快很多,然后不断重复,估计刷个十次八次应该就能记住 80%
- 手写 js,最长公共前缀能写出来真的不容易啊
// 二叉树最大深度
function maxDepth(root) {
if (!root) return 0;
let leftH = maxDepth(root.left);
let rightH = maxDepth(root.right);
let h = 1 + Math.max(leftH, rightH);
return h;
}
// 二叉树最小深度
function minDepth(root) {
if (!root) return 0;
let leftH = minDepth(root.left);
let rightH = minDepth(root.right);
if (root.left != null && root.right == null) {
return leftH + 1;
} else if (root.left == null && root.right != null) {
return rightH + 1;
}
return 1 + Math.min(leftH, rightH);
}
// 最长公共前缀
// 输入:strs = ["flower","flow","flight"]
// 输出:"fl"
// 横向扫描
var longestCommonPrefix = function (arr) {
var findLong = (str1, str2) => {
var len = Math.min(str1.length, str2.length);
var index = 0;
while (index < len && str1[index] === str2[index]) {
index++;
}
return str1.substr(0, index);
};
if (!arr || arr[0].length == 0) return "";
var prefix = arr[0];
for (let i = 0; i < arr.length; i++) {
let item = arr[i];
prefix = findLong(prefix, item);
if (item.length === 0) {
break;
}
}
return prefix;
};
// 纵向扫描
var longestCommonPrefix = function (arr) {
if (!arr || arr[0].length == 0) return "";
var count = arr.length;
let len = arr[0].length;
for (let i = 0; i < len; i++) {
for (let j = 1; j < count; j++) {
if (i === arr[j].length || arr[0].charAt(i) != arr[j].charAt(i)) {
return arr[0].substr(0, i);
}
}
}
return arr[0];
};
- 长时间不写 promise,还是会忘记 Promise.resolve/Promise.finally
- 手写 class 和模拟继承两个题还是不知道怎么写,怎么调用?跌跌撞撞
function mockExtends(child, parent, staticProp) {
let proto = Object.create(parent.proptotype);
proto.constructor = child;
child.prototype = proto;
Object.setPrototypeOf(child, parent);
}
const checkNew = function (instance, con) {
if (!(instance instanceof con)) {
throw new TypeError(
`Class constructor ${con.name} cannot be invoked without 'new'`
);
}
};
const defineProperties = function (target, obj) {
for (const key in obj) {
Object.defineProperty(target, key, {
configurable: true,
enumerable: false,
value: obj[key],
writable: true,
});
}
};
const createClass = function (con, proto, staticAttr) {
proto && defineProperties(con.prototype, proto);
staticAttr && defineProperties(con, staticAttr);
return con;
};
// 用法
function Person(name) {
checkNew(this, Person);
this.name = name;
}
var PersonClass = createClass(
Person,
{
getName: function () {
return this.name;
},
},
{
getAge: function () {},
}
);
[^abc]
常见简写方式:
\d // 数字
\D // 非数字
\w // [0-9a-zA-Z_]
\W // [^0-9a-zA-Z_]
\s // [\t\v\n\r\f]
\S // [^\t\v\n\r\f]
1. {m,} // 至少出现m次
2. {m} // 出现m次
3. ? // 出现0次或者1次,等价于{0,1}
4. + // 至少出现1次,等价于{1,}
5. * // 出现>=0次,等价于{0,}
- 贪婪匹配 VS 惰性匹配?正则本身是贪婪的,会尽可能的多匹配符合模式的字符
let regex = /\d{2,5}/g;
let string = "123 1234 12345 123456";
// 贪婪匹配
// string.match(regex) // [ 123, 1234, 12345, 12345 ]
// 惰性匹配
let regex2 = /\d{2,5}?/g;
// string.match(regex) // [ 12, 12, 34, 12, 34, 12, 34, 56 ]
量词后面加一个?,即变成了惰性匹配
贪婪量词 惰性量词
{m,n} {m,n}?
{m,} {m,}?
? ??
+ +?
* *?
1206
- 910,与其自我紧张更希望被干掉拿补偿,与其干掉还希望能在继续 🐶1 年
- 算法题这棵大树早晚要被我干掉,在不断重复肌肉记忆的时候,稍微多一丢丢思考就行,要求不高
- 看到了一个牛皮的独立开发者,不仅技术强,产品思维也很厉害730 天:从 0 到每月 45000 美金,看完之后,自己 emo 了很久,对于未来充满迷茫
1207
- 每次面试都这么痛苦,为啥呢?能促使你学习,面对自己的不足,不是挺好的一件事,可自己就是那么没用,老是特别紧张,能不能想到一种办法让自己不紧张?
痛苦说明自己在进步
- 树转数组
var listTree = [
{
id: 1,
name: "部门1",
pid: 0,
children: [
{
id: 2,
name: "部门1-1",
pid: 1,
children: [
{
id: 4,
name: "部门1-1-1",
pid: 2,
children: [],
},
],
},
{
id: 3,
name: "部门1-2",
pid: 1,
children: [
{
id: 5,
name: "部门1-2-1",
pid: 3,
children: [],
},
],
},
],
},
{
id: 6,
name: "部门2",
pid: 0,
children: [
{
id: 7,
name: "部门2-1",
pid: 6,
children: [],
},
],
},
{
id: 8,
name: "部门3",
pid: 0,
children: [],
},
];
// BFS
function treeToArr(tree) {
if (!tree) return [];
let queue = [];
queue = queue.concat(tree);
let res = [];
while (queue.length) {
let cur = queue.shift();
if (cur.children && cur.children.length) {
queue = queue.concat(cur.children);
delete cur.children;
}
res.push(cur);
}
return res;
}
treeToArr(listTree);
1208
最近一周经历过三场面试,给自己一个清晰的认识,总结来说:
- 框架八股文准备不足(思维导图继续补充完善)
- 算法基础实在太差了,这个任重道远(每天要保持刷算法的节奏)
- 脑子不够灵活,前端解决实际问题能力不够,这方面不是练习就能提升的,很头痛(如何举一反三?)
总结就是 太笨了,知识死记硬背,没有太多自己的沉淀,随便出一个稍微变种的题目就能把自己挂了,比如说
// 增加数组原型 group 方法,实现自定义分类
// 预期结果
var result = {
bigger: [4, 5],
smaller: [1, 2, 3],
};
var array = [1, 2, 3, 4, 5]; // sorted
var res = array.group((num, index, array) => {
return num > 3 ? "bigger" : "smaller";
});
看看人家三年的面试题,比你问的问题难多了,我 7 年自叹不如!
- 你一开始准备 100 道题,后面觉得不够,准备了 150 道 JS 题,你想这下肯定够了吧,谁知道面试的时候,可能需要储备 100*5 = 500 道题,你就是井底之蛙,啥也不懂,脑子也不够灵活,简直废物一个! 算法: 300,目前已有 150,每天 2-3 道题,三个月 150 道题差不多 js: 200,目前已有 140 在补充 60 道题
面试官说:你不要太着急,想好了有思路再去下手,总结起来除了话术要循序渐进,还要自己平时多积累,不可能现场在想在总结,这个肯定会有问题,给人一种说话说不全的感觉
1209
- 913,随时做好战斗的准备,多积累面试题,不错过每一天
- 现在的面试题不再拘谨于过去已出现的面试题,要灵活运用已学的知识点,发散思维
1211
- 915,忙了一天降级,Nodejs 端渲染页面逻辑还没处理完,明天继续处理
- 算法题手写岛屿数量和螺旋矩阵
function numIslands(grid) {
let dfs = (grid, r, c) => {
if (!isArea(grid, r, c) || grid[r][c] != "1") return;
grid[r][c] = "2";
dfs(grid, r - 1, c);
dfs(grid, r + 1, c);
dfs(grid, r, c - 1);
dfs(grid, r, c + 1);
};
var isArea = (grid, r, c) =>
r >= 0 && r < grid.length && c >= 0 && c < grid[0].length;
let count = 0;
for (let r = 0; r < grid.length; r++) {
for (let c = 0; c < grid[0].length; c++) {
if (grid[r][c] == "1") {
dfs(grid, r, c);
count = count + 1;
}
}
}
return count;
}
// 螺旋矩阵
// 输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
// 输出:[1,2,3,6,9,8,7,4,5]
var spiralOrder = function (nums) {
if (!nums.length) return [];
let res = [];
let up = 0;
let down = nums.length - 1;
let left = 0;
let right = nums[0].length - 1;
while (true) {
// 从左向右
for (let i = left; i <= right; i++) {
res.push(nums[up][i]);
}
if (++up > down) break;
// 从上往下
for (let i = up; i <= down; i++) {
res.push(nums[i][right]);
}
if (--right < left) break;
// 从右往左
for (let i = right; i >= left; i--) {
res.push(nums[down][i]);
}
if (--down < up) break;
// 从上往下
for (let i = down; i >= up; i--) {
res.push(nums[i][left]);
}
if (++left > right) break;
}
return res;
};
1212
- 916,Promise 不能只简单实现基础版,Promise/A+实现规范
- 算法题还需要进一步补充弹药库,现在掌握的算法题太少了,不够成系统
1213
- 917,准备购买血糖仪,准备打印照片以及洗照片和相框
- 老妈每天要吃这么多药,连续吃三个月?算一下每天要花多少钱就知道了
胃复春胶囊 4 粒 每日三次 一天 12 粒
枸酸莫沙必利片 1 片 每日三次 一天三片
奥美拉陛肠溶胶囊 1 粒 每日两次 一天 2 粒
康复新液 10ml 每日三次 一天 30ml
1214
- 918,每天搞个算法题,记录下,发到小红书上
- 面试经典 150 题
- LeetCode 热题 100
- LeetCode 75
- 30 天 JavaScript 挑战
1215
- 919,接雨水/每日温度/螺旋矩阵/岛屿数量,继续保持,每天至少 1 道
- 手写异步串行,长时间不写忘记了
function asyncSeries(arr) {
let [first, ...others] = arr;
return (...arg) => {
return others.reduce((pre, cur) => {
return pre.then((val) => cur(...val));
}, Promise.resolve(first(...arg)));
};
}
1216
- 920,上海温度低于 0 度
二叉树的类型
- 满二叉树:如果一棵二叉树只有度为 0 的结点和度为 2 的结点,并且度为 0 的结点在同一层上,则这棵二叉树为满二叉树。
- 完全二叉树:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层(h 从 1 开始),则该层包含 1~ 2^(h-1) 个节点。
- 二叉搜索树: 二叉搜索树是一个有序树。若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;它的左、右子树也分别为二叉排序树
- 平衡二叉搜索树:又被称为 AVL(Adelson-Velsky and Landis)树,且具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过 1,并且左右两个子树都是一棵平衡二叉树。
1217
- 921,0117951 0217 981 0317 1011 过完年即超过第一家公司
- 看了下从 7 月开始有意练习手写代码,远远不够,需要理解+手写,重复肌肉记忆,重复肌肉记忆
- 什么时候才能练习完基本的手写代码部分,到底什么时候,我对目前的进度有点不满意了,打不到预期,预期是元旦左右要搞完基本的手写代码题
- 从 12 月 17 号开始刷 DP 题目,状态转移,如何转移的,刷到 12 月底,也就是 13 道题
1218
- 922
- 服务上云,把物理机全都下掉,首先压测得到需要的服务器配置,然后容器部署扩容,然后更改路径,最后物理机缩容
- 怀念小时候的时光,现在长大了,经济压力越来越大
1219
- 923
- 昨晚偷懒了,没刷题,今天给补回来,看到一个 27 岁的前端程序猿,刷到了 330 道题,挺厉害的,比我强太多了,所以还需要磨练自己,保持刷题的习惯,贵在坚持
- 手写 js,终于 cover 掉了几乎 99%的 Promise
// Promise
class Promise {
constructor(exec) {
this.value = undefined;
this.reason = undefined;
this.onFulfillCbs = [];
this.onRejectCbs = [];
this.status = "pending"; // fulfilled rejected
const resolve = (val) => {
if (this.status === "pending") {
setTimeout(() => {
this.value = val;
this.status = "fulfilled";
this.onFulfillCbs.forEach((fn) => fn(val));
});
}
};
const reject = (reason) => {
if (this.status === "pending") {
setTimeout(() => {
this.reason = reason;
this.status = "rejected";
this.onRejectCbs.forEach((fn) => fn(reason));
});
}
};
try {
exec(resolve, reject);
} catch (e) {
reject(e);
}
}
then(onFulfilled, onRejected) {
// 参数校验,确保一定是函数
onFulfilled =
typeof onFulfilled === "function" ? onFulfilled : (val) => val;
onRejected =
typeof onRejected === "function"
? onRejected
: (reason) => {
throw reason;
};
let p1 = new Promise((reoslve, reject) => {
if (this.status === "pending") {
this.onFulfillCbs.push(() => {
this.resolvePromise(p1, onFulfilled(this.value), resolve, reject);
});
this.onRejectCbs.push(() => {
this.resolvePromise(p1, onRejected(this.reason), resolve, reject);
});
}
if (this.status === "fulfilled") {
this.resolvePromise(p1, onFulfilled(this.value), resolve, reject);
}
if (this.status === "rejected") {
this.resolvePromise(p1, onRejected(this.reason), resolve, reject);
}
});
return p1;
}
resolvePromise(p1, res, resolve, reject) {
try {
if (p1 == res) {
throw new TypeError("Chaining cycle detected for promise");
}
if (res instanceof Promise) {
res.then(resolve);
} else {
resolve(res);
}
} catch (err) {
reject(err);
throw Error(err);
}
}
static resolve(val) {
return new Promise((resolve, reject) => {
if (val instanceof Promise) {
val.then(resolve);
} else {
resolve(val);
}
});
}
static reject(reason) {
return Promise.reject(reason);
}
finally(cb) {
return this.then(
(val) => {
return Promise.resolve(cb()).then(() => val);
},
(reason) => {
return Promise.resolve(cb()).then(() => reason);
}
);
}
// all/any/race/allSettled
static all(arr) {
return new Promise((resolve, reject) => {
let res = [];
for (let [index, item] of arr.entries()) {
Promise.resolve(item).then(
(val) => {
if (index == arr.length - 1) {
resolve(res);
}
res[index] = val;
},
(error) => {
reject(error);
}
);
}
});
}
static allSetteld(arr) {
return Promise.all(
arr.map((item) => {
Promise.resolve(item).then(
(val) => {
return {
value: val,
status: "fulfilled",
};
},
(err) => {
return {
reason: err,
status: "rejected",
};
}
);
})
);
}
}
trans(123456)
// trans(123456) —— 十二万三千四百五十六
// trans(100010001)—— 一亿零一万零一
function numToCn(n) {
n = n.toString();
let units = ["", "十", "百", "千"];
let nums = ["零", "一", "二", "三", "四", "五", "六", "七", "八", "九"];
let res = "";
let len = n.length - 1;
for (let i = 0; i <= len; i++) {
let cur = n[i];
if (cur != "0") {
if (i >= 1 && n[i - 1] === "0") res += nums[0];
res += nums[cur] + units[len - i];
}
}
if (n.length === 2 && n[0] == "1") {
res = res.slice(1);
}
return res;
}
function trans(n) {
let isLose = n < 0;
n = Math.abs(n).toString();
let res = [];
let units = ["", "万", "亿"];
let len = n.length; // 5
for (let i = len; i > 0; i -= 4) {
res.push(numToCn(n.slice(Math.max(0, i - 4), i)));
}
for (let i = 0; i < res.length; i++) {
res[i] = res[i] + units[i];
}
if (isLose) {
res.push("负");
}
return res.reverse().join("");
}
trans(12345);
1220
- 924,组织架构调整了,已经不知道调整几次了,习惯了,目前最重要的事做好打硬仗的准备,算法和 nodejs 知识点是每天必须要准备的。戈戈都已经要去拼多多了,还是挺厉害的,真心羡慕。自己也要努力,对得起这个年纪,最后一次选择了,希望自己能找到一个满意的下家
- 继续 dp 手写,背包问题
// weight 1,3,4
// value 15 20 30
// 求背包容量是6如何装物品使价值最大化
function beibag(weight, value, size) {}
- 今天要做的一个是 nodejs 中的进程和线程,一个是二叉树和数组之间的遍历以及多叉树的遍历,感觉现在对这块遍历特别混淆,说不清道不明的
1221
- 925,每周三四都睡不着,也不知道有啥心事,总是感觉不安。始终没有找到归属感和责任感,希望下一家能为之奋斗努力!
- 或许这是最后一次认真对待,开弓没有回头箭,干就对了,每天积累一点点,就行起房子似的,一点点看他起高楼。有点烦躁,不知道为啥,如果休息不好,会形成良性循环,到底啥时能复习 80%
- 还有十天就走完 2023 年,时间过的真快,我还是这么穷
1222
- 926,工作环境真的是醉了,克服一切阻力,远离这里,不在一个世界的人,不要有任何的交集。
- 又到了一年一度的绩效考核时间,
1223
- 927
- 手撕快排,基本都是超时,过不了 AC
var sortArray = function (nums) {
var partion = (nums, left, right) => {
let pivot = right;
let leftIndex = left;
for (let i = left; i < right; i++) {
if (nums[pivot] > nums[i]) {
swap(nums, leftIndex, i);
leftIndex++;
}
}
swap(nums, leftIndex, pivot);
return leftIndex;
};
var quickSort = (arr, left, right) => {
if (left >= right) return;
mid = partion(arr, left, right);
quickSort(arr, left, mid - 1);
quickSort(arr, mid + 1, right);
return nums;
};
if (nums.length < 2) return nums;
return quickSort(nums, 0, nums.length - 1);
};
function swap(arr, i, j) {
var temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
- 插入排序,比之前的好理解!!哇塞,确实好记多了
function insertSort(arr) {
for (let i = 1; i < arr.length; i++) {
let j = i;
while (j > 0 && arr[j - 1] > arr[j]) {
swap(arr, j - 1, j);
j--;
}
}
return arr;
}
function swap(arr, i, j) {
let temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
insertSort([11, 222, 1, 2, 55, 22, 10]);
二叉树分类
二叉树分为满二叉树(full binary tree)和完全二叉树(complete binary tree)。
- 满二叉树:一棵深度为 k 且有 2 ^ k - 1 个节点的二叉树称为满二叉树
- 完全二叉树:完全二叉树是指最后一层左边是满的,右边可能满也可能不满,然后其余层都是满的二叉树称为完全二叉树(满二叉树也是一种完全二叉树)
二叉树结构
从图中我们可以看出二叉树是从上到下依次排列下来,可想而知可以用一个数组来表示二叉树的结构,从下标 index( 0 - 8 ) 从上到下依次排列。
- 二叉树左侧节点表达式 index*2 + 1。例如:以根节点为例求左侧节点,根节点的下标为 0,则左侧节点的序数是 1 ,对应数组中的值为 1
- 二叉树右侧节点表达式 index*2 + 2。例如:以根节点为例求右侧节点,根节点的下标为 0,则右侧节点的序数是 2 ,对应数组中的值为 8
- 二叉树叶子节点表达式 序数 >= floor( N / 2 )都是叶子节点(N 是数组的长度)。例如:floor( 9 / 2 ) = 4 ,则从下标 4 开始的值都为叶子节点
二叉堆特征
二叉堆是一个完全二叉树,父节点与子节点要保持固定的大小关系,并且每个节点的左子树和右子树都是一个二叉堆。
二叉堆根据排序不同,可以分为最大堆和最小堆
- 最大堆:根节点的键值是所有堆节点键值中最大者,且每个父节点的值都比子节点的值大
- 最小堆:根节点的键值是所有堆节点键值中最小者,且每个父节点的值都比子节点的值小
通过上面的讲述想必大家对二叉堆有了一定的理解,那么接下来就是如何实现。以最大堆为例,首先要初始化数组然后通过交换位置形成最大堆。
1225
- 929 圣诞节快乐,周六和周日刷题不是很满意,拖沓了,这两天弥补一下
- 没有自己负责的核心业务,早晚被干掉,还是继续蹲面试题不,没有安全感
- 打开格局,拓宽职业道路,往后段靠一靠,延长程序员职业生涯。例如: 1.熟悉 Nodejs,需要掌握 Nestjs 框架 2.有容器化/存储/数据库/消息队列/编排调度等场景运维背景知识 3.还想再学一门新语言,学习 golang 或者 python,明年的规划
- 先把记账系统整一整,整体走一遍流程
1226/27
- 931
- 手撕基础代码
// 如何拦截构造函数进行拦截调用
function Person(name) {
this.name = name;
}
var t1 = new Person("cpp"); // ok
var notT1 = Person.call(t1, "cpp");
console.log(t1, notT1);
// 如何改造
function Person1(name) {
if (new.target != undefined) {
this.name = name;
} else {
throw new Error("必须使用new关键词");
}
}
var t1 = new Person1("cpp"); // ok
var notT1 = Person1.call(t1, "cpp");
SWR 这个名字来自于 stale-while-revalidate?如何实现 swr 机制
1228
- 932,过完年就快突破 1000 天了,正式突破第一家的在职时间
- 继续练习手写 js, 对象扁平化和字符串相乘
// 实现变量的锁定
function mockFreeze(obj) {}
1229
- 933
- 元旦提前回南京了
1230
- 年终回归,整理手写题和面试题
- 明年技术上的规划和展望
1231
- 935
- 新年快乐,2024 年,正式迈入 33 岁了