JS 中的事件循环机制
这个网站可以可视化运行 https://www.jsv9000.app
这个面试经常问诶,但是我好几次回答的都是不尽如人意,这次来好好搞懂一下看看 😡。
单线程的 JS首先我们需要知道 JS 是单线程的,为啥 😧?
因为一开始设计之初,他只是一个浏览器的脚本语言,主要就是操控 DOM 和与用户互动,如果他是多线程的话,那么就会出现很多问题,比如多个线程同时操作一个 DOM,谁知道会发生啥。
当然 JS 也可以多线程,下面引用阮一峰博客的话:
为了利用多核 CPU 的计算能力,HTML5 提出 Web Worker 标准,允许 JavaScript 脚本创建多个线程,但是子线程完全受主线程控制,且不得操作 DOM。所以,这个新标准并没有改变 JavaScript 单线程的本质。
任务队列那这样我们可以认为,所有的任务都放到了一个队列里面,然后一个一个的执行。但是这样应该还会有问题,比如有的任务计算量很大,有的任务占用时间很长,这样就会导致后面的任务无法执行,这样就会导致页面卡死(因为浏览器的渲染线程和 JS 线程是互斥的)。
如果是前者,CPU 忙不过来 ...
了解一下 Array.flatMap()
MDN 地址:Array.prototype.flatMap()
这个 API 我之前都没听过,所以看到他还挺好奇的,简单了解一下,然后看看他能做啥啥 🤓。
介绍MDN 是这么介绍的:
flatMap() 方法对数组中的每个元素应用给定的回调函数,然后将结果展开一级,返回一个新数组。它等价于在调用 map() 方法后再调用深度为 1 的 flat() 方法(arr.map(…args).flat()),但比分别调用这两个方法稍微更高效一些。
😯 我再看一下例子,感觉理解的差不多了。
const arr1 = [1, 2, 1]const result = arr1.flatMap(num => (num === 2 ? [2, 2] : 1))console.log(result) // [ 1, 2, 2, 1 ]
他就是先 map() 然后 flat(),这样就可以实现改变长度的 map🤪。
基本语法flatMap(cb)flatMap(cb, thisArg)
第一个就是回调函数,参数和 map 一样,不多介绍了。第 ...
TEDxTalks 创作家的行为习惯 笔记
The surprising habits of original thinkers | Adam Grant | TED
记录原创者(originals)不墨守成规,指的是那些独立思考,创新的人。
对于创造力来说,拖延症并不是一件坏事。有的人在犯拖延症的时候想到了最有创造力的点子。调查表明,提早做完事的员工,他们的创造力不如一些中度拖延症的员工。
任务的想法会在我们的脑海中活跃,拖延行为让我们有时间发散思考,以非线性的模式思考,然后获得意想不到的突破。
“You call it Procrastinating. I call it thinking.” —— Aaron Sorkin
Procrastinating is a vice when it comes to productivity, but it can be a virtue for creativity.拖延症会导致生产力的下降,但也可能会是新创造的摇篮。
先动者优势并不对,研究发现,很多个行业中,先动者的失败率是 47%,改变者失败率只有 8%。
想做原创者,你 ...
JS 中的箭头函数众所周知,箭头函数是 ES6 引入的新特性之一,我们也知道他相当于是简写的函数,还知道没有自己的 this,以及不能作为构造函数,但是具体深究一下看看,还有哪些是我们不知道的吧 🤷♂️
基本用法函数声明:
let foo = name => { console.log(name)}
他也就等同于
function foo(name) { console.log(name)}
没啥区别,其中(name)外面的()是可以省略的。
然后呢他还有一些简写,比如{ }中直接就返回值了,可以这么简写:
let foo = name => `name: ${name}`let foo2 = name => { return `name: ${name}`}
他们俩是一样的,不过需要注意,返回对象也是{ }😫,这个时候需要包一层( )
let foo = name => ({ name ...
【浏览器是如何运作的】笔记看了一个视频,感觉 UP 分享的质量很高,简要记录一下视频内容,这是视频地址:【干货】浏览器是如何运作的?
浏览器历史这里不多说,让我惊讶的一点是,Chrome 的内核 Chromeium,是基于苹果开源的 Webkit 开发的 🥸,不得不说,🍎 真 🐮。
进程浏览器有多个进程,进程之间通过 IPC(进程间通信管道)来通信。
早期的浏览器是单进程的,这也就引发了很多问题:
页面不稳定: 其中一个线程卡死可能导致整个进程出问题,单标签页卡死 -> 浏览器卡死
不安全: 浏览器之间共享数据,JS 线程可以随意访问浏览器进程内的所有数据
不流畅: 一个进程负责多种
为了解决这些问题,看在采用了多进程的浏览器结构
浏览器进程:控制地址栏、书签、前进后退,负责与其他进程协调工作
网络进程:收发网络请求
GPU 进程:渲染浏览器界面
插件进程:控制管理插件
渲染器进程:渲染 tab 标签页内的所有内容
输入 URL 后的事视频主要分析的是网络线程获取到数据之后发生的事情。
首先网络线程通过 SafeBrowsing 检查 URL 是否安全。
通过后通知 ...
Mac 开荒配置预计下个月入职字节,这里就准备一下拿到的 Mac 需要配置的东西吧。
设置
三指拖拽:辅助功能,指针控制,触控板选项,拖移样式
软件安装:隐私与安全性,允许从任意来源安装。如果没有任何来源选项就终端输入sudo spctl --master-disable
连按窗口标题以最小化
弹跳打开
应用程序指示灯
最近使用的应用
显示隐藏快捷键:option+command+D
软件
Mos: 鼠标滚动优化
iShot: 截图软件
iCopy: 剪切板软件
自动切换输入法: 和名字一样
FastZip: 解压缩软件
Better And Better: 鼠标手势软件
MagicNotch: 刘海屏拓展软件
paper.er: 壁纸软件
Folder by Color: 文件夹颜色图标修改
Itsycal: bar 上的日历
Bartender5: 刘海管理软件
uTools: 快捷软件
Menuwhere: 任意地点呼出左上角 🍎 按钮的菜单
Rectangle: 窗口管理软件
IINA: 视频播放器
OnlySwitch: 小工具
One Switch: ...
2024-2-23 字节商业化 三面 过问
自我介绍
项目难点,多说几个
怎么学前端的
视频、文章、书
手写,'a.b.c' -> { a: b: { c: null } }
反问
人多少
部门面向啥
广告平台,toB
为啥前几面没有怎么问计网/算法
看人,因人而异
总结18min 就结束了 😯,我猜是急着下班吧,快到不可思议。
JS 中对象的 key 的排列顺序面试官:来你看一下这个顺序应该是什么?
const obj = {}obj['b'] = 100obj['a'] = 33obj[2] = 0obj[1] = 10console.log(Object.keys(obj))
我:🤡 我只知道 obj 的 key 会做自动转换,数字会转换成字符串,然后输出的顺序还是不一定和声明时一样,我猜测是1 2 a b。
结果我还是错的,答案是1 2 b a,面试官也建议我去了解看看这个到底是啥机制 🥴。
实验看看直接去代码试试看,我们知道对象的键可以为字符串或者 symbol,当使用数字作为 key 时其实会被转换成字符串
字符串const obj = { b: 1, a: 1, d: 1, c: 1,}console.log(Object.keys(obj))// b, a, d, c
可以看出来,和我们声明的顺序是一致的,所以我们可以猜测,只有字符串的时候,遍历的顺序和我们的声明顺序是一样的,下面看看数字呢?
数字c ...
2024-2-19 字节商业化 二面 过问
自我介绍
项目:odin 低代码
有没有自己封装组件:用的 element 的
画布定位:相对和绝对,放大怎么办?
实习:性能优化、协作方式、需求评审开发
Vue
Vue2 和 Vue3 的区别
响应式,v2 对数组怎么处理的:原型链改写,还深问了是哪些方法。
v3 有哪些 hooks
异步组件了解吗,怎么用
CSS 布局有哪些
flex、grid
了解 sticky 吗? 知道用的不多,所以后面就不怎么问 css 了
Promise 的状态还有方法
TS 了解多少、enum 咋用
setTimeout 一定准嘛,怎么实现精准的
手写模版字符串,思路对,正则不咋熟没写出来
let infos = { name: 'xiaoming', age: 23, city: 'beijing', school: 'PKU',}toTmplString('my name is ${name},I am ${age& ...
JS 中的浅拷贝与深拷贝拷贝数据这是一个很常见的操作,像基本类型我们可以直接赋值,没啥影响 🥳,但如果是引用类型的话,直接赋值是会出问题的,看个小例子:
let obj = { name: '111' }let copyObj = objcopyObj.name = 'copy'console.log(copyObj) // { name: 'copy' }console.log(obj) // { name: 'copy' }
我们可以发现一个很明显的问题,改的是copyObj啊,为啥子原来的obj里面的东东也被改了 😭?
这就涉及到引用类型的存储方式了,引用类型的存储是存储在堆内存中的,而栈内存中存储的是指向堆内存中的地址。所以说,我们上面的赋值就是把地址给了copyObj,他们俩指向的是同一个地址,所以改一个另一个也会被改。
那么我们怎么解决这个问题呢?这就需要了解浅拷贝和深拷贝了 🤗。
浅拷贝浅拷贝指的是只复制对象或数组本身,而不 ...