153期
1. 说说vue中的diff算法,以及key的作用?
2. 说说react中的diff算法?
3. CSS3新增了哪些特性?
上面问题的答案会在第二天的公众号(程序员每日三问)推文中公布
也可以小程序刷题,已收录500+面试题及答案
152期问题及答案
1. 在做文件断点续传时,如何判断2次选择的是同一个文件?
在前端实现文件断点续传时,为了确保用户两次选择的是同一个文件,我们通常需要在选择文件时收集一些文件的元数据信息,并且在上传之前和之后都能够进行匹配校验。以下是几种前端可以采用的方法来判断用户是否两次选择了同一个文件:
文件名和文件大小:使用JavaScript可以轻松访问到文件的名字(
file.name
)和大小(file.size
)。通过比较两次选择的文件的名字和大小,我们就能够做出初步的判断。
function isSameFile(file1, file2) {
return file1.name === file2.name && file1.size === file2.size;
}
最后修改时间:HTML5 File API允许访问文件的最后修改时间(
file.lastModified
),这可以作为判断的额外依据。
function isSameFile(file1, file2) {
return file1.name === file2.name &&
file1.size === file2.size &&
file1.lastModified === file2.lastModified;
}
计算文件Hash:虽然在前端计算大文件的哈希值可能会造成性能问题,但是我们可以通过选择文件的一部分(比如头部)来计算哈希值以提供足够的准确性同时减少性能开销。
function calculateHash(file, callback) {
const reader = new FileReader();
reader.onload = function(e) {
const hash = CryptoJS.MD5(e.target.result).toString();
callback(hash);
};
const blob = file.slice(0, 2000); // 只取文件的前2000字节来计算哈希值,避免性能问题
reader.readAsBinaryString(blob);
}
function isSameFile(oldFile, newFile, callback) {
calculateHash(oldFile, (oldHash) => {
calculateHash(newFile, (newHash) => {
const isSame = oldFile.name === newFile.name &&
oldFile.size === newFile.size &&
oldHash === newHash;
callback(isSame);
});
});
}
请注意在这个示例中我使用了 CryptoJS
来计算MD5哈希值,你需要确保你已经在你的项目中引入了CryptoJS库。
利用服务端资源:实际开发中,前端通常会把文件的元信息(如文件名、大小、最后修改时间等)发送到服务端,并得到一个文件标识符(比如文件ID或者计算得到的文件哈希)。之后的上传操作都会使用这个标识符来辨识文件,以便实现断点续传。
在实际应用场景中,可以综合考虑以上的几种方法,取得性能与准确性的平衡。通常文件名、大小和最后修改时间的组合就能解决大多数情况下的断点续传识别问题。而对于特别关心安全性和准确性的情况,可以采用哈希值计算的方式,但应注意其对性能的影响。
2. 浏览器为什么有跨域限制,目的是什么?
浏览器的跨域限制(也称为同源策略 Same-Origin Policy, SOP)是一种安全机制,用于防止恶意行为,比如网站间脚本攻击(Cross-Site Scripting, XSS)、数据盗窃、CSRF(Cross-Site Request Forgery)等。它确保了一个源(origin)的文档或脚本在没有明确权限的情况下,不能与不同源的资源进行交互。
“源”是由以下三个部分组成的组合:
协议(例如,http 或 https)
域名(例如,example.com)
端口号(例如,80或443)
只有当这三个都相同时,两个URL才属于同一个源。同源策略主要有以下目的:
隔离潜在的恶意文件:防止恶意网站读取另一个网站的数据,例如,一个钓鱼网站试图通过Ajax读取银行网站的数据并获取用户的个人财务信息。
保护用户的隐私安全:用户可能在不同网站中输入敏感信息,同源策略可以阻止其他网站通过JavaScript获得这些信息,保护用户不受跨站脚本攻击。
减小CSRF攻击风险:CSRF可以利用用户的登录状态在不同站点间进行请求伪造,同源策略限制了来自其他源的请求对当前源数据的操控,因此阻碍了CSRF攻击的实施。
然而,随着Web应用变得越来越复杂,需要更多的交互式功能和多元化的数据源,跨域通信变得不可或缺。为了满足这种需求,在不牺牲安全性的基础上,Web 提供了一些方法来绕过同源策略,允许安全的跨域通信,例如:
CORS(跨源资源共享):通过服务器端设置HTTP响应头,如
Access-Control-Allow-Origin
,可以安全地允许某些跨域请求。JSONP(仅限于GET请求):利用
<script>
标签没有跨域限制的特性来发送跨域请求。PostMessage API:允许来自不同源的窗口间安全地传递数据。
WebSockets:虽然会进行来源判断,但不受同源策略的限制,允许跨域通信。
Document.domain:可以在有相同父域的情况下通过设置
document.domain
来允许子域之间的通信。
这些方法都是在确保安全的前提下有选择性地放宽了同源策略的限制,使得现代的Web应用可以在保护用户安全的同时提供丰富的功能。
3. 为什么推荐使用transform: translateX(10px);而不是left:10px;来实现动画?
推荐使用transform: translateX(10px)
而不是left: 10px
来实现动画的主要原因在于性能和效率。以下是一些关键点的详细解释:
硬件加速:
transform
属性(包括translateX
)通常会触发GPU(图形处理单元)硬件加速,而left
属性则不会。GPU对于处理图形和动画非常擅长,因此使用transform
可以得到更流畅的动画效果,尤其是在移动设备和性能较低的机器上。**复合图层(Compositing Layers)**: 当使用
transform
属性进行动画时,浏览器可以创建一个单独的复合图层来对元素进行处理。这意味着在动画过程中无需重新绘制(repaint)或重排(reflow)文档中的其他元素,因为动画是在其自己的层上进行的,这极大提高了性能。避免重排(Reflow): 使用
left
属性时,如果元素的位置发生变化,浏览器可能需要重新计算页面布局,因为它影响了文档流。这个过程称为重排或回流,可能会导致整个页面或页面的大部分进行重新渲染,这是一个比较耗资源的操作。相反,对transform
属性的更改不会影响文档流,因此通常不会引起重排。避免重绘(Repaint): 即使
left
属性的变化不导致重排,它也可能导致元素自己或其周围区域的重绘,重绘是计算图形重新在屏幕上绘制的过程,这也比起通过transform
触发的合成操作来说,代价更高。更佳的性能体验: 因为
transform
可以提供更加平滑和快速的动画,因而能够带给用户更好的体验,尤其是在那些需要频繁和复杂动画的应用中。
考虑到上述性能优势,大多数情况下我们确实应该使用transform
来实现动画。不过,要注意的是,在某些复杂的动画和布局情境中,仍可能需要考虑使用left
、top
等属性,比如当动画的目的是为了改变元素在文档流中的实际位置时。此时,应当综合性能和需求来做出决策。
我要提问
如果你遇到有趣的面试题,或者有想知道的前端面试题,可以在下面的小程序提问,收到问题后会在第一时间为你解答。
我要出题
学习不打烊,充电加油只为遇到更好的自己,每天早上9点纯手工发布面试题,每天坚持花20分钟来学习与思考,在千变万化,类库层出不穷的今天,不要等到找工作时才狂刷题,提倡每日学习。