hello,大家好,今天的原创文章由团队金牌导师 uncle13 创作,内容是一位同学的真实面试经历(敏感信息已经删),最近在找工作的同学,可以来看看这次100分钟的一面自己掌握的怎么样了。
以下是某独角兽的前端一面面试题,将近两个小时的面试。下面简单总结一下,大家也可以自测一下相关知识点。
项目描述:介绍自己做过的项目
技术栈:
在移动端开发中,通常使用navigator.userAgent
字符串来判断设备平台。通过解析这个字符串,可以识别出是Android、iOS还是微信内置浏览器。此外,也可以使用第三方库如react-native-device-info
(React Native环境下)来简化这一过程。
在设计移动端页面时,一般遵循响应式设计原则,使用视口单位(vw/vh)、百分比或Flexbox布局来处理页面的尺寸和宽高。同时,使用媒体查询(Media Queries)来适配不同屏幕尺寸的设备。对于React Native,则利用平台的样式系统(如StyleSheet.create)和布局组件(如View、Text、Image等)来构建适应不同屏幕尺寸的界面。
根据设计稿的尺寸计算rem值,通常需要先设定一个基准宽度(如设计稿宽度为750px),然后基于这个宽度将设计稿中的px值转换为rem值。例如,如果基准宽度为750px,且html的font-size设置为100px(即1rem=100px),则设计稿中宽度为150px的元素,其rem值为1.5rem。
目前移动端适配方式除了rem布局外,还有vw/vh布局、百分比布局、Flexbox布局、Grid布局以及使用PostCSS插件(如postcss-pxtorem)自动转换px到rem等。
在React函数式组件中,组件的调用通常发生在以下几个阶段:
函数被调用的次数取决于上述事件发生的次数以及组件的优化程度(如使用React.memo、useMemo、useCallback等)。
React组件会在以下情况下触发更新:
如果子组件没有接收任何props,父组件渲染时,子组件可能会跟着重新渲染,但这取决于子组件的实现。如果子组件内部有状态(state)或副作用(如useEffect),并且这些状态或副作用的依赖项没有变化,那么子组件可能不会进行不必要的重新渲染(尽管其函数体可能会被调用)。然而,如果子组件的实现不够优化(如使用了不纯的函数),则每次父组件渲染时,子组件都会重新渲染。
React.memo是一个高阶组件,用于对函数式组件进行记忆化。它仅对props进行浅比较,如果props没有变化,则不会重新渲染组件,而是返回上一次的渲染结果。这有助于避免在父组件重新渲染时,不必要的子组件重新渲染。
组件返回的JSX在编译阶段会被转换成React.createElement的调用。例如,<div>Hello, World!</div>
会被转换成React.createElement('div', null, 'Hello, World!')
。这样做是为了在JavaScript环境中构建虚拟DOM树,并最终由React的渲染引擎将虚拟DOM转换为真实的DOM。
React函数式组件中的hooks需要遵循以下写法规范:
use
前缀(useState
、useEffect
等)。这些规范是出于React内部实现机制的考虑。React通过Hooks的顺序来追踪组件的状态和副作用,因此如果Hooks的调用顺序在组件的不同渲染之间发生变化,可能会导致状态丢失或不可预测的行为。
React Fiber是在React 16中引入的,它的诞生背景是为了解决React在动画、布局、手势操作等场景下性能不足的问题。Fiber是一个新的协调引擎,它重新实现了React的核心算法,使得React能够更高效地处理组件的更新、渲染和卸载。
Fiber旨在解决的主要问题包括:
除了手动优化(如使用React.memo、useMemo、useCallback等),React还提供了以下自动优化方案:
a. 项目经验和框架
如果有服务端渲染的项目经验,通常会使用React的SSR库如Next.js或Gatsby。这些框架提供了内置的SSR支持,简化了开发过程。
b. 服务端渲染原理
服务端渲染的原理是在服务器上执行React组件,生成HTML字符串,然后将这个字符串发送给客户端浏览器。这样,用户首次访问页面时就可以立即看到完整渲染的页面,而无需等待JavaScript执行和DOM构建。
c. 服务端处理
服务端需要做以下处理才能生成DOM结构:
Vue的响应式系统是基于ES5的Object.defineProperty
(在Vue 3中使用了Proxy)来实现的。当一个响应式数据(如组件的data属性)被访问或修改时,Vue会拦截这些操作,并触发依赖更新。
依赖收集的过程如下:
React和Vue在性能方面各有优势,但通常差异不大,具体取决于应用的复杂度、优化程度以及使用的特定功能和库。
一些可能的差异包括:
在React中,可以使用useMemo
或自定义的Hook来实现类似Vue computed属性的功能。useMemo
可以缓存一个复杂计算的结果,并在依赖项发生变化时重新计算。通过封装useMemo
,可以创建一个自定义Hook来模拟computed属性的行为。
我了解并熟悉多种编程语言,包括Java、Python、C++等。这些语言在各自的应用领域都有广泛的使用,并且它们的学习有助于拓宽我的技术视野和提高解决问题的能力。
进程:是系统进行资源分配和调度的一个独立单元,它是应用程序运行的载体。每个进程都有独立的内存空间和系统资源。
线程:是进程的一个实体,是CPU调度和分派的基本单位,它是进程中的实际运作单位。线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
资源占用:进程是资源分配的基本单位,它拥有独立的内存空间和系统资源。而线程是CPU调度的基本单位,它共享进程的资源,包括内存、文件句柄等。
独立性:进程是独立运行的程序,拥有独立的地址空间,而线程是进程中的一个实体,它不能独立运行,必须依赖于所属的进程。
开销:由于进程拥有独立的资源,因此进程间的切换需要保存和恢复较多的上下文信息,开销较大。而线程切换的开销较小,因为它们是共享进程的资源的。
通信:进程间的通信较为复杂,需要通过IPC(进程间通信)机制来实现。而线程间的通信则相对简单,因为它们共享进程的内存空间,可以直接读写共享变量。
并发性:多线程的并发性更高,因为它们是共享同一进程的资源的,可以在同一进程中并发执行多个任务。而多进程虽然也可以实现并发,但每个进程都需要独立的资源,因此并发性较低。
浏览器的事件循环是JavaScript执行的基础,它允许JavaScript代码在浏览器环境中异步执行。浏览器的事件循环主要包括以下几个部分:
调用栈(Call Stack):JavaScript引擎用调用栈来跟踪函数执行。当代码执行时,它被压入调用栈,并在执行完毕后从栈中弹出。
事件队列(Event Queue):当异步事件(如点击事件、定时器到时等)发生时,它们会被放入事件队列中等待处理。
事件循环(Event Loop):事件循环不断检查调用栈是否为空,并且事件队列中是否有待处理的事件。如果调用栈为空,事件循环会从事件队列中取出一个事件,并将其对应的回调函数放入调用栈中执行。
这个过程会不断重复,形成了浏览器的事件循环。它允许JavaScript代码在等待异步操作完成时,不会阻塞UI的渲染和其他任务的执行。
浏览器的渲染流程主要包括以下几个步骤:
解析HTML:浏览器将HTML文档解析成DOM树。
构建CSSOM:浏览器解析CSS文件,构建CSSOM(CSS Object Model)树。
合并DOM树和CSSOM树:浏览器将DOM树和CSSOM树合并成一个渲染树(Render Tree)。渲染树只包含需要显示的节点和样式信息。
布局(Layout):浏览器根据渲染树计算每个节点的几何信息,如位置和大小。
绘制(Paint):浏览器将渲染树的节点绘制到屏幕上。这一步会生成绘制层(Paint Layers),并填充像素信息。
合成(Compositing):浏览器将多个绘制层合并成一个或多个图像,然后显示在屏幕上。如果页面中有动画或滚动,浏览器会重新执行布局、绘制和合成步骤来更新屏幕显示。
这个过程是浏览器渲染网页的基本流程,它确保了网页能够正确地显示在用户的屏幕上。### 21. HTTP和HTTPS的区别
HTTP(HyperText Transfer Protocol)和HTTPS(HyperText Transfer Protocol Secure)是两种用于在网络上传输数据的协议,它们之间有几个关键的区别:
安全性:
端口号:
URL前缀:
http://
开头。https://
开头。性能:
证书:
应用场景:
HTTP/1.x 和 HTTP/2 是HTTP协议的两个不同版本,它们之间存在多个主要区别:
二进制协议:
多路复用(Multiplexing):
头部压缩(Header Compression):
服务器推送(Server Push):
性能改进:
浏览器的同源策略(Same-Origin Policy)是一种安全策略,它限制了来自不同源的文档或脚本对当前文档读取或设置某些属性时的权限。这里的“源”指的是协议、域名和端口号三者的组合。
作用:
防止跨站请求伪造(CSRF):CSRF攻击允许攻击者诱使用户在不知情的情况下对受信任的网站执行操作。同源策略可以阻止第三方网站向受信任网站发送请求,从而减轻CSRF攻击的风险。
防止数据泄露:通过限制不同源之间的交互,同源策略可以防止恶意网站读取或修改来自其他网站的敏感数据。
维护用户隐私:同源策略确保了用户数据只在用户明确信任的网站之间共享,从而保护了用户的隐私。
然而,有时候我们需要在不同源之间共享数据或功能,这时可以通过跨域资源共享(CORS)、JSONP、代理服务器等技术来实现。### 24. CORS(跨源资源共享)
CORS(Cross-Origin Resource Sharing)是一种机制,它使用额外的HTTP头部来告诉浏览器允许一个网页运行的脚本从不同于它自身来源的服务器上请求资源。这解决了由同源策略引起的跨域请求问题。
CORS的工作原理:
预检请求(Preflight Request):对于某些类型的跨域请求(如PUT、DELETE、或包含自定义HTTP头部的GET/POST请求),浏览器会首先发送一个OPTIONS请求到服务器,询问服务器是否允许跨域请求。这个OPTIONS请求被称为“预检请求”。
服务器响应:服务器在接收到预检请求后,会检查请求的源(Origin)是否在自己的允许列表中。如果是,服务器会返回一个包含适当CORS头部的响应,指示浏览器继续执行实际的请求。
实际请求:一旦浏览器收到包含适当CORS头部的响应,它就会继续发送实际的请求。
浏览器处理响应:浏览器会检查响应中的CORS头部,以确定是否应该将响应数据暴露给前端JavaScript代码。
CORS相关的HTTP头部:
Access-Control-Allow-Origin
:指定哪些网站可以参与跨站请求。Access-Control-Allow-Methods
:指定允许跨站请求的方法。Access-Control-Allow-Headers
:指定允许跨站请求中携带的自定义头部。Access-Control-Expose-Headers
:指定哪些头部信息可以安全地暴露给前端JavaScript代码。Access-Control-Max-Age
:指定预检请求的结果可以被缓存多久。浏览器缓存机制是一种减少服务器请求、加快页面加载速度的技术。它通过缓存静态资源(如HTML、CSS、JavaScript、图片等)到客户端(浏览器),并在后续请求中直接使用缓存资源,而不是重新从服务器加载。
浏览器缓存的几种类型:
强缓存(Cache-Control/Expires):
Cache-Control
和 Expires
是控制强缓存的HTTP头部。协商缓存(Last-Modified/If-Modified-Since/ETag/If-None-Match):
If-Modified-Since
或 If-None-Match
),询问资源自上次请求后是否有修改。浏览器缓存的优点:
浏览器缓存的缺点:
HTTP状态码(HTTP Status Code)是服务器用来表示网页服务器HTTP响应状态的3位数字代码。这些状态码被分成五类,以指示请求的结果或错误。
HTTP状态码的分类:
1xx(信息性状态码):表示接收到请求,正在处理。
2xx(成功状态码):表示请求已成功被服务器接收、理解、并接受。
3xx(重定向状态码):表示需要客户端采取进一步的操作才能完成请求。
4xx(客户端错误状态码):表示请求包含语法错误或无法完成请求。
5xx(服务器错误状态码):表示服务器在处理请求的过程中发生了错误。
浏览器安全策略是一系列旨在保护用户免受网络攻击和恶意软件侵害的措施。这些策略包括但不限于:
同源策略(SOP):如前所述,限制来自不同源的文档或脚本对当前文档读取或设置某些属性时的权限。
内容安全策略(CSP):通过HTTP头部告诉浏览器哪些外部资源是允许的,从而减少XSS(跨站脚本)攻击的风险。
X-Frame-Options:防止网站被嵌入到frame或iframe中,从而避免点击劫持攻击。
X-Content-Type-Options:防止浏览器尝试基于响应的实体内容去“嗅探”并忽略响应的Content-Type头部。这有助于减少基于MIME类型混淆的攻击。
X-XSS-Protection:尽管现代浏览器已不再推荐使用(因为现代浏览器内置了更强大的XSS防护机制),但X-XSS-Protection头部曾用于启用或禁用浏览器的XSS过滤器。
HTTP Strict Transport Security(HSTS):通过HTTP头部告诉浏览器仅通过HTTPS与服务器通信,增加通信的安全性。
公共密钥基础设施(PKI)和SSL/TLS证书:用于加密HTTPS通信,确保数据传输的机密性和完整性。
Cookie安全属性:如HttpOnly和Secure属性,用于减少跨站脚本(XSS)和中间人攻击(MITM)的风险。
这些安全策略共同构成了现代Web应用安全的基石,帮助保护用户数据和隐私免受威胁。### 28. Web API 和 RESTful API
Web API(Web Application Programming Interface)是一种允许不同软件应用程序之间通信的接口。它使用HTTP协议,通过请求和响应的方式,在不同的系统或应用之间交换数据。Web API可以支持多种数据格式,如JSON、XML等,以便不同的客户端(如Web浏览器、移动应用、桌面应用等)都能方便地与之交互。
RESTful API(Representational State Transfer)是一种设计Web API的架构风格,而不是一个协议或标准。RESTful API遵循REST原则,强调资源的表示、状态转移和客户端-服务器模型。RESTful API使用HTTP方法(如GET、POST、PUT、DELETE等)来操作资源,每个方法都对应着对资源的特定操作。例如,GET方法用于获取资源,POST方法用于创建资源,PUT方法用于更新资源,DELETE方法用于删除资源。
RESTful API的特点:
无状态(Stateless):服务器不会保存客户端的状态信息,每次请求都是独立的,包含了服务器所需的所有信息。
可缓存(Cacheable):客户端可以缓存响应数据,以减少服务器负载和网络带宽消耗。
分层系统(Layered System):客户端无法直接知道它是否与最终的服务器进行交互,还是通过中间层(如负载均衡器、代理服务器等)进行交互。
统一接口(Uniform Interface):客户端和服务器之间通过标准的HTTP方法和头部进行通信,使得不同的系统和服务能够相互通信。
资源导向(Resource-Oriented):RESTful API将网络上的所有内容都视为资源,并使用URI来定位资源。
RESTful API与Web API的关系:
WebSocket是一种在单个TCP连接上进行全双工通讯的协议。它使得客户端和服务器之间的数据交换变得更加简单,允许服务器主动向客户端推送数据。WebSocket在需要高实时性、低延迟的Web应用中非常有用,如在线游戏、实时聊天应用、实时数据可视化等。
WebSocket的特点:
全双工通信:客户端和服务器之间可以同时发送和接收数据,而不需要像HTTP那样,每次请求都需要等待响应。
持久连接:WebSocket建立连接后,除非明确关闭,否则连接将一直保持打开状态,减少了频繁建立连接的开销。
较少的控制开销:在连接建立后,WebSocket服务器和客户端之间交换数据时,只需要携带少量的数据头信息,从而减少了控制开销。
支持二进制消息:WebSocket支持发送二进制数据,而不仅仅是文本数据,这使得它非常适合传输图片、音频、视频等多媒体内容。
浏览器提供了多种存储机制,以便在客户端持久化数据。这些存储机制包括:
Cookie:最初用于在客户端存储用户会话信息,但由于大小限制和安全性问题,现在更多用于存储简单的标识符(如会话ID)。
LocalStorage:允许你在用户的浏览器中存储数据,没有过期时间,直到被显式删除。它存储的数据会保存在浏览器的本地,即使用户关闭了浏览器窗口,数据仍然保留。
SessionStorage:与LocalStorage类似,但它存储的数据在页面会话期间可用,当页面会话结束时(如关闭浏览器标签页或窗口),数据将被清除。
IndexedDB:一个低级的API,用于客户端存储大量结构化数据。它提供了事务支持、索引、查询等高级功能,但使用起来相对复杂。
WebSQL(已废弃):曾经被提出作为Web数据库的规范,但由于安全性和兼容性等问题,并未被广泛采纳和支持,现已被废弃。
Cache API:用于控制和管理HTTP请求的缓存。它提供了一种方式来存储和检索请求/响应对,以便在后续请求中快速访问。
这些存储机制各有优缺点,开发者可以根据应用的需求和场景选择合适的存储方式。
还没有使用过我们刷题网站(https://fe.ecool.fun/)或者前端面试题宝典的同学,如果近期准备或者正在找工作,千万不要错过,题库主打无广告和更新快哦~。
我们团队的前端辅导也做了将近2年了,陆陆续续辅导了几百位同学,分享一下最近几个结束辅导的回访。