本篇介绍运行环境相关知识点和题目。包括浏览器加载和渲染机制,性能优化,web安全。网页在浏览器加载和运行,这些内容必须掌握,也是面试常考。
一、网页加载和渲染相关
1、从输入url到显示出页面的整个过程
整个规程可以分为三个部分,分别是:
- 加载资源的形式
- 加载资源的过程
- 渲染页面的过程
1、加载资源的形式:网页加载资源主要由三部分构成,
- html代码
- 媒体文件,如图片、视频等
- javascript代码 css代码
2、加载资源的过程
- DNS解析:域名 -> IP地址
- 浏览器根据IP地址向服务器发起 http请求
- 服务器处理http请求,并返回给浏览器
3、渲染页面的规程
- 根据HTML代码生成DOM Tree
- 根据CSS代码生成CSSOM
- 将DOMTree和CSSOM整合形成Render Tree
- 根据Render Tree渲染页面
- 遇到script标签则暂停渲染,优先加载并执行JS代码,完成再继续
- 直至把Render Tree渲染完成
2、为何把CSS放在header中
将CSS放在header中的主要原因是为了提高网页的加载速度和性能。当浏览器加载网页时,它会首先读取HTML文档的头部,然后再加载页面的主要内容。因此,将CSS代码放在header中,可以确保浏览器在加载页面内容之前就已经读取了CSS样式,从而避免了页面加载时的闪烁和混乱。
此外,将CSS放在header中还可以提高网页的可维护性和可读性。通过将所有样式代码集中在一个地方,可以更容易地管理和更新样式,还可以提高搜索引擎优化(SEO)效果。
3、为何建议把JS放在body最后
如果js放在header中,浏览器遇到script标签时,会停止HTML文档的解析并开始下载javascript文件。这会导致用户在浏览器下载和执行javascript代码时卡按到空白页面或加载缓慢的情况。
如果将js放在body底部,浏览器先加载HTML和CSS,然后去下载和执行js代码,这样可以加快页面的加载速度。避免出现js代码阻塞页面渲染的情况。
4、window.onload和DOMContentLoaded区别
onload是页面全部资源加载完成才会执行,包括图片、视频等。
DOMContentLoaded是渲染完成即可执行,此时图片、视频还可能没有加载完。
二、性能优化
- 一个综合性问题,没有标准答案,但要求尽量全面
- 某些细节问题可能会单独提问:手写防抖、节流
- 只关注核心点,针对面试
1、性能原则
- 多使用内存、缓存或其他方法
- 减少CPU计算量,减少网络加载耗时
- (适用于所有编程的性能优化--空间换时间)
2、让加载更快
- 减少资源体积:压缩代码
- 减少访问次数:合并代码,SSR服务端渲染,缓存
- 使用更快的网络:CDN
3、让渲染更快
- CSS放在head,JS放在body最下面
- 尽早开始执行JS,用DOMContentLoaded触发
- 懒加载(图片懒加载,上滑加载更多)
- 对DOM查询进行缓存
- 频繁DOM操作,合并到一起插入DOM结构
- 节流和防抖
三、手写防抖(debounce)代码
使用场景:
- 监听一个输入框的文字变化后,触发change事件
- 直接用keyup事件,则会频发触发change事件
- 防抖:用户输入结束 或暂停时,才会触发change事件
创建一个debounce.html文件,实现代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input type="text" id="input1"/>
<script src="./debounce.js"></script>
</body>
</html>
创建一个debounce.js文件,实现代码:
function debounce(fn,delay=500) {
let timer = null
return function () {
if(timer) {
clearTimeout(timer)
}
timer = setTimeout(()=>{
fn.apply(this,arguments)
timer = null
},delay)
}
}
const input1 = document.getElementById('input1')
input1.addEventListener('keyup', debounce(function (e) {
console.log('input1', input1.value)
}, 500))
四、手写节流(throttle)代码
使用场景
- 拖拽一个元素时,要随时拿到该元素被拖拽的位置
- 直接用drag事件,则会频繁触发,很容易导致卡顿
- 节流:无论拖拽速度多快,都会每隔100ms触发一次
创建一个throttle.html文件,实现代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#div1 {
width: 100px;
height: 50px;
border: 1px solid #ccc;
}
</style>
</head>
<body>
<div id="div1" draggable="true">可拖拽</div>
<script src="./throttle.js"></script>
</body>
</html>
创建一个throttle.js文件,实现代码:
function throttle(fn, delay=500) {
let timer = null
return function () {
if(timer) {
clearTimeout(timer)
}
timer = setTimeout(()=>{
fn.apply(this, arguments)
timer = null
},delay)
}
}
const div1 = document.getElementById('div1')
div1.addEventListener('drag',throttle(function (e) {
console.log('e',e.offsetX, e.offsetY )
}, 500))
五、常见的web前端攻击方式有哪些
- XSS跨站请求攻击
- XSRF跨站请求伪造
XSS(跨站脚本攻击)是一种常见的Web攻击,攻击者利用Web应用程序中存在的漏洞,将恶意脚本注入到受害者的浏览器中,从而实现攻击目的。
而跨站请求攻击(CSRF)是一种利用受害者已登录的身份来执行未经授权的操作的攻击。攻击者会通过某些手段(如钓鱼邮件、恶意网站等)诱使受害者访问一个包含恶意代码的网页,从而在受害者的浏览器中执行攻击代码。
攻击者通常会利用XSS攻击来实现CSRF攻击。攻击者将恶意代码注入到Web应用程序中,当受害者访问该页面时,恶意代码会自动发送请求到目标网站,利用受害者的登录凭据执行未经授权的操作。
为了防止XSS和CSRF攻击,开发人员应该采取一些预防措施,包括:
- 对用户输入进行过滤和验证,防止恶意代码注入。
- 在Web应用程序中实现CSRF令牌机制,防止未经授权的操作。
- 避免使用敏感操作的GET请求,而应该使用POST请求。
- 对Web应用程序进行安全审计,包括代码审计和渗透测试,以发现并修复潜在的漏洞。
- 使用安全的编程实践,如避免使用eval()函数和动态拼接SQL查询语句等。
- 及时更新Web应用程序和相关组件的版本,以防止已知漏洞的利用。
- 对于Web应用程序中的敏感操作,应该采取额外的安全措施,如双因素认证、IP限制等。