【前端面试3】初中级难度

文章目录

  • 前言
    • [1. Vue3 和 Vue2 的响应式原理](#1. Vue3 和 Vue2 的响应式原理)
    • [2. TS 的 declare 关键字](#2. TS 的 declare 关键字)
    • [3. TS 中 type 和 interface 的区别](#3. TS 中 type 和 interface 的区别)
    • [4.JS 的 map 详解](#4.JS 的 map 详解)
    • [5. 前端跨页面通信](#5. 前端跨页面通信)
    • [6. JS 脚本延迟加载的方式](#6. JS 脚本延迟加载的方式)
    • [7. Vue 模板是如何编译的](#7. Vue 模板是如何编译的)
    • [8. Vue3 相比 Vue2 在编译阶段的改进](#8. Vue3 相比 Vue2 在编译阶段的改进)
    • [9. Vue 的 scoped 和 CSS 原理](#9. Vue 的 scoped 和 CSS 原理)
    • [10.什么是虚拟 DOM?如何实现?](#10.什么是虚拟 DOM?如何实现?)

前言

大家好,今天是冲击中级工程师第三天,让我们来完成今天的面试题打卡。

1. Vue3 和 Vue2 的响应式原理

答案:vue2基于 Object.defineProperty,在组件初始化时,遍历 data 中的所有属性,使用 Object.defineProperty 把它们转为 getter/setter。它的缺点是

1.无法检测对象属性的添加或删除(所以有了 this.$set)。

2.对数组支持不佳:需要重写数组的原型方法(push, pop等)。

3.性能开销:必须递归遍历整个对象树。

vue3是基于proxy来进行实现的,直接监听整个对象,而不是属性。不再需要特殊的set和get方法。性能方面也会更强,因为只有在访问某个嵌套对象时,才会按需进行下一层的响应式代理(懒处理)。

2. TS 的 declare 关键字

答案:核心作用是:告诉编译器,某个东西已经存在了,别报错(声明这个东西)。

当使用第三方 JS 库,或者在 HTML 中引入了全局变量时,TS 并不认识它们。

用法:

declare var/let/const:声明全局变量。

declare function:声明全局函数。

declare module:声明一个模块(常用于 .d.ts 文件)

3. TS 中 type 和 interface 的区别

直接看表格:

特性 interface(接口) type(类型别名)
定义范围 只能定义对象/函数结构 可以定义任意类型(联合类型、元组、原始类型等)
合并能力 同名自动合并(Declaration Merging) 不允许重名
继承方式 通过 extends 继承 通过 &(交叉类型)模拟继承
适用场景 库、框架的 API 定义,方便扩展 复杂的组合类型、联合类型

4.JS 的 map 详解

答案:需要知道的第一件事:map有三个参数

Array.prototype.map((value, index, array) => { ... })

第一个参数:value (当前值):当前正在处理的数组元素。

第二个参数:index (下标):当前元素的索引(从 0 开始)。

第三个参数:array (原数组):调用 map 方法的数组对象本身。

经典面试题:

javascript 复制代码
console.log(['1', '2', '3'].map(parseInt));

输出:[ 1, NaN, NaN ]

解析:parseInt有两个参数,第一个参数是,目标值,第二个参数是进制。

javascript 复制代码
parseInt(string, radix)

所以等价于

parseInt('1', 0) // index = 0

parseInt('2', 1) // index = 1

parseInt('3', 2) // index = 2

第一条,radix传入0,采用默认进制,输出10,第二条,进制是1,radix再2-36之间,所以报错输出NaN,第三条,不存在三进制,同样输出NaN

5. 前端跨页面通信

答案:

1.localStorage + storage 事件,最经典的方式。

javascript 复制代码
// A 页面
localStorage.setItem('msg', JSON.stringify({ text: 'hello' }));

// B 页面
window.addEventListener('storage', (e) => {
  if (e.key === 'msg') {
    console.log(JSON.parse(e.newValue));
  }
});

2.BroadcastChannel

javascript 复制代码
const channel = new BroadcastChannel('my-channel');

// 发送
channel.postMessage({ text: 'hello' });

// 接收
channel.onmessage = (e) => console.log(e.data);

3.SharedWorker

javascript 复制代码
// shared-worker.js
onconnect = (e) => {
  const port = e.ports[0];
  port.onmessage = (ev) => {
    port.postMessage(ev.data);
  };
};

4.Service Worker

javascript 复制代码
navigator.serviceWorker.controller.postMessage('hello');

6. JS 脚本延迟加载的方式

答案:主要分为以下几种

javascript 复制代码
<script defer>

异步加载,但在 DOM 解析完成后、DOMContentLoaded 事件前执行。

多个 defer 脚本按顺序执行。

javascript 复制代码
<script async>

异步加载,一旦加载完立即执行(会中断 DOM 解析)。

执行顺序不确定,谁先下好谁执行。

动态创建 DOM:通过 document.createElement('script') 插入,默认行为类似 async。

放在 body 底部:最原始的方式,确保 HTML 先显示。

7. Vue 模板是如何编译的

解析:Vue 的模板编译流程是:先将模板字符串解析成抽象语法树(AST),分析指令和绑定关系;然后根据 AST 生成渲染函数(render function);运行时渲染函数会创建虚拟 DOM(VNode),并通过虚拟 DOM 对比(diff)更新真实 DOM,实现高效渲染。整个过程把模板转换为可执行函数,保证数据变化能快速映射到页面。

8. Vue3 相比 Vue2 在编译阶段的改进

也是直接看对比

改进点 说明
静态节点提升(Hoisting) 将不会变化的静态节点在编译阶段提升到渲染函数外,避免每次渲染重复创建,提高性能。
静态属性标记(Patch Flag) 编译器会为动态节点打标记(Patch Flag),运行时只更新变化部分,减少 diff 开销。
更轻量的 AST Vue 3 编译器生成的 AST 更精简,减少解析和生成成本。
Fragment 支持 模板可返回多个根节点(Fragment),编译器会生成对应的 VNode 列表。
v-once / v-memo 优化 提前处理一次性渲染或条件渲染,避免重复计算。
Tree-shaking 更友好 编译输出函数更模块化,有助于去掉未使用指令/API,减小包体积。

9. Vue 的 scoped 和 CSS 原理

解析:给组件内的所有 DOM 加上一个独一无二的动态属性(如 data-v-f3f3eg)。这样就保证了组件内的css的独立,编译后的例子如下:

javascript 复制代码
HTML: <div class="title" data-v-f3f3eg></div>
CSS: .title[data-v-f3f3eg] { color: red; }

追问:那么如果使用了深度选择器,会怎么样?

答案:深度选择会穿透这个样式,去修改里面的子组件。因此,如果你使用了深度选择时,会修改到相同类名的样式,这个在使用框架时要注意。

10.什么是虚拟 DOM?如何实现?

解析:通俗来讲,虚拟DOM实际上就是一个普通的js对象,是对真实DOM的一种轻量级描述。使用它配合diff算法能够减少不必要的真实DOM操作。

实现步骤:

1创建 (h 函数):接收 tag, props, children,返回一个 JS 对象。

  1. 渲染 (render 函数):递归遍历这个 JS 对象,用 document.createElement 创建真实节点并挂载。

  2. 更新 (diff/patch):对比新旧两个 JS 对象,找出差异,只给真实 DOM 补丁。

#总结

今天面试题就到这里,让我们每天学习几个题,一起成长。管他难易,获得成长就好。明天见。

相关推荐
霍理迪2 小时前
JS作用域与预解析
开发语言·前端·javascript
华清远见成都中心2 小时前
GPIO(通用输入输出)面试中高频问题
单片机·面试·职场和发展
切糕师学AI2 小时前
.NET Core Web 中的健康检查端点(Health Check Endpoint)
前端·kubernetes·.netcore
蓉妹妹2 小时前
在React中使用Scroll嵌套Scroll,出现里面Scroll滚动条超出高度却滚动没反应的问题,解决方案添加nestedScrollEnabled
javascript·react native·react.js
rosmis2 小时前
地铁病害检测系统软件改进记录-2-02
开发语言·前端·javascript
css趣多多2 小时前
解决ui组件flex1容器底部被撑开的问题
前端
乔江seven2 小时前
【python轻量级Web框架 Flask 】2 构建稳健 API:集成 MySQL 参数化查询与 DBUtils 连接池
前端·python·mysql·flask·web
Alaaaaaaan3 小时前
[DevOps]使用github-action工具部署docker容器(实现提交代码一键推送部署到服务器)
服务器·前端·docker·容器·github
摘星编程3 小时前
在OpenHarmony上用React Native:Spinner自定义样式
javascript·react native·react.js