java面试刷题(【手撕面试题】JavaScript(高频知识点三))
目录
面试官:什么是防抖和节流 ,他们的应用场景有哪些?
面试官:js中什么是可选操作符 ,如何访问数组?
面试官:请简述一下 event loop
面试官:请简述 node/v8 中的垃圾回收机制
面试官:如何删除项目中没有使用到的 package?
面试官:请你谈谈 js 中在 new 的时候发生了什么?
面试官:浏览器的剪切板中如何监听复制事件?
面试官:如何实现页面文本不可复制?
面试官:异步加载 JS 脚本时 ,async 与 defer 有何区别?
面试官:前端如何实现文件上传功能?
每天10道题 ,100天后 ,搞定所有前端面试的高频知识点 ,加油!!! ,在看文章的同时 ,希望不要直接看答案 ,先思考一下自己会不会 ,如果会 ,自己的答案是什么?想过之后再与答案比对 ,是不是会更好一点,当然如果你有比我更好的答案 ,欢迎评论区留言 ,一起探讨技术 之美 。
面试官:什么是防抖和节流,他们的应用场景有哪些?
我:呃~ ,防抖和节流以及他们的应用场景总结如下:
防抖:顾名思义就是防止抖动 ,以免把一次事件误认为是多次 ,敲键盘就是一个每天都会接触到的防抖操作 ,在JS中有好多防抖的场景 ,例如:登录 、发短信等按钮避免用户点击太快 ,以致于发送了多次请求 ,需要防抖;调整浏览器窗口大小时 ,resize 次数过于频繁 ,造成计算过多 ,此时需要一次到位 ,就用到了防抖;代码如下 ,可以看出来防抖重在清零:
function debounce(f, wait) { let timer; return (...args) => { clearTimeout(timer); timer = setTimeout(() => { f(...args); }, wait); }; }节流:节流,顾名思义 ,控制水的流量 。控制事件发生的频率 ,如控制为 1s 发生一次,甚至 1 分钟发生一次 。与服务端(server)及网关(gateway)控制的限流 (Rate Limit) 类似 ,在JS中有好多节流的场景 ,例如:scroll事件 ,每隔一秒计算一次位置信息等;浏览器播放事件 ,每个一秒计算一次进度信息等;input 框实时搜索并发送请求展示下拉列表 ,每隔一秒发送一次请求 (也可做防抖);代码如下 ,可以看出来节流重在加锁:
function throttle(f, wait) { let timer; return (...args) => { if (timer) { return; } timer = setTimeout(() => { f(...args); timer = null; }, wait); }; }总结:
防抖:防止抖动 ,单位时间内事件触发会被重置 ,避免事件被误伤触发多次 。代码实现重在清零 clearTimeout 。防抖可以比作等电梯 ,只要有一个人进来 ,就需要再等一会儿 。业务场景有避免登录按钮多次点击的重复提交 。
节流:控制流量 ,单位时间内事件只能触发一次 ,与服务器端的限流 (Rate Limit) 类似 。代码实现重在开锁关锁 timer=timeout; timer=null 。节流可以比作过红绿灯,每等一个红灯时间就可以过一批 。
面试官:js中什么是可选操作符 ,如何访问数组?
我:呃~ ,?. 操作符,可以嵌套获取对象的属性值 。通过获取对象属性获得的值可能是 undefined 或 null 时 ,可选链操作符提供了一种方法来简化被连接对象的值访问 。具体使用方式如下:
const o = {}; // 添加可选链之前 o && o.a && o.a.b && o.a.b.c && o.a.b.c.d; // 添加可选链之后 o?.a?.b?.c?.d; const obj = { a: [1, 2], b() {} }; // 访问数组 obj?.a?.[0]; //使用方法 obj?.b?.();面试官:请简述一下 event loop
我:呃~ ,因为 JS 是单线程的 ,单线程就意味着 ,所有任务需要排队 ,前一个任务结束 ,才会执行后一个任务。为了解决排除等待问题 ,JS 的任务分为同步任务(synchronous)和异步任务(asynchronous) 。 所有同步任务都在主线程上执行 ,形成一个 Stack) 。异步任务(如果是 WebAPI 则会进入 WebAPI ,例如 ajax setTimeout)不进入主线程 ,而是进入另一 Callback Queue。同步任务顺序执行 ,只有执行栈中的同步任务执行完了 ,系统才会读取任务队列中可以执行的异步任务,才会把此异步任务从事件队列中放入执行栈中执行 ,如此循环 ,直至所有任务执行完毕 。这就是 EventLoop 。代码如下:
setTimeout(() => console.log(0)); new Promise((resolve) => { console.log(1); resolve(2); console.log(3); }).then((o) => console.log(o)); new Promise((resolve) => { console.log(4); resolve(5); }) .then((o) => console.log(o)) .then(() => console.log(6));输出内容如下:
面试官:请简述 node/v8 中的垃圾回收机制
我:呃~,v8 中的垃圾回收机制分为如下三种:
Scavenge:工作在新生代 ,把 from space 中的存活对象移至 to space
Mark-Sweep:标记清除 。新生代的某些对象由于过度活跃会被移至老生代 ,此时对老生代中活对象进行标记 ,并清理死对象
Mark-Compac:标记整理 。
当一个函数执行结束之后 ,JavaScript 引擎会通过向下移动 ESP 来销毁该函数保存在栈中的执行上下文 。 要回收堆中的垃圾数据 ,就需要用到 JavaScript 中的垃圾回收器了 。 代际假说(The Generational Hypothesis) ,是垃圾回收领域中一个重要的术语 ,后续垃圾回收的策略都是建立在该假说的基础之上的 ,所以很是重要 。 代际假说有以下两个特点:
1)大部分对象在内存中存在的时间很短 ,简单来说 ,就是很多对象一经分配内存 ,很快就变得不可访问;
2)是不死的对象 ,会活得更久 。 在 V8 中会把堆分为新生代和老生代两个区域,新生代中存放的是生存时间短的对象 ,老生代中存放的生存时间久的对象 。 ● 副垃圾回收器 ,主要负责新生代的垃圾回收 。 ● 主垃圾回收器,主要负责老生代的垃圾回收 。
使用增量标记算法 ,可以把一个完整的垃圾回收任务拆分为很多小的任务 ,这些小的任务执行时间比较短 ,可以穿插在其他的 JavaScript 任务中间执行 ,增强用户体验 。
面试官:如何删除项目中没有使用到的 package?
我:呃~ ,可以采用 depcheck 来完成这件事 ,代码如下:
npm install depcheck -g面试官:请你谈谈 js 中在 new 的时候发生了什么?
我:呃~ ,在js中进行new的时候 ,发生了下面的四步:
1)创建了一个新对象
2)链接到原型
3)绑定这个指向
4)返回这个对象
function _new() { let obj = {}; let Con = [].shift.call(arguments); obj.__proto__ = Con.prototype; let result = Con.apply(obj, arguments); return typeof obj === "object" ? obj : {}; }面试官:浏览器的剪切板中如何监听复制事件?
我:呃~ ,可以采用原生js发方式进行监听 ,如下:
// 在 HTML 元素上 <input oncopy="cb" /> // 在 JS 中获取具体元素 document.querySelector("p").oncopy = cb; document.oncopy = cb; // 或 document.querySelector("p").addEventListener("copy", cb); document.addEventListener("copy", cb);面试官:如何实现页面文本不可复制?
我:呃~ ,有CSS和JS两种方法 ,以下任选其一或结合使用即可。
使用CSS如下:
user-select: none;使用JS如下,监听 selectstart 事件 ,禁止选中 ,当用户选中一片区域时,将触发 selectstart 事件 ,Selection API 将会选中一片区域 。禁止选中区域即可实现页面文本不可复制:
document.body.onselectstart = (e) => { e.preventDefault(); }; document.body.oncopy = (e) => { e.preventDefault(); };面试官:异步加载 JS 脚本时 ,async 与 defer 有何区别?
我:呃~ ,在正常情况下 ,即 <script> 没有任何额外属性标记的情况下 ,有几点共识JS 的脚本分为加载 、解析 、执行几个步骤 ,简单对应到图中就是 fetch (加载) 和 execution (解析并执行)JS 的脚本加载(fetch)且执行(execution)会阻塞 DOM 的渲染 ,因此 JS 一般放到最后头
而 defer 与 async 的区别如下:
相同点:异步加载 (fetch)
不同点:
async 加载(fetch)完成后立即执行 (execution) ,因此可能会阻塞 DOM 解析;
defer 加载(fetch)完成后延迟到 DOM 解析完成后才会执行(execution)** ,但会在事件 DomContentLoaded 之前
面试官:前端如何实现文件上传功能?
我:呃~ ,将 input 的类型设置为 file ,再加一个按钮就行 ,如下:
<input type="file" ref="referenceUpload" @change="onUpload"></input> <button type="primary" style="margin: 0px 0px 0px -83px;">上传文件</button>创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!