还在背题?理解这些前端基础,面试问答自然 “丝滑”

699 阅读16分钟

前端面试不慌张,基础知识全掌握!

哈喽,各位未来的前端大佬们!👋 又到了我们“面试不慌张”系列的时间啦!今天,咱们要聊聊前端那些你以为“没啥区别”但其实“大有乾坤”的基础知识。别看它们平时默默无闻,关键时刻可是能让你在面试官面前“闪闪发光”的哦!✨

废话不多说,咱们直接上干货!

💡 第一章:HTML那些事儿

🔗 href vs src:傻傻分不清楚?

面试官:hrefsrc都是引用URL的标签属性,它们有什么区别?

你:这...不都是引用资源吗?(内心OS:又来一个“没区别”系列!)

别看它们都和URL打交道,但它们的“职责”可是大不相同!理解了它们,你就能更好地理解浏览器是如何加载和处理资源的。

通俗解释:

想象一下,你正在看一本武功秘籍(当前文档)。

  • href 就像是秘籍里的“目录”或者“索引”,它告诉你哪里有更多的武功招式(网络资源),但它本身不包含这些招式。当你点击目录里的某个招式时,你才会去翻到那一页(浏览器会去下载并处理那个资源)。

    比如,<link href="./style.css" rel="stylesheet" />,这里的href就是告诉浏览器,去这个地址找样式表,但它不会立即把样式表的内容“搬”到当前页面来,只是建立了一个链接关系。

    再比如,<a href="https://xdclass.net"></a>,你点击这个链接,浏览器才会跳转到新的页面。

  • src 就像是秘籍里的“插画”或者“内功心法”,它直接把内容“嵌入”到秘籍里。当你翻到这一页时,插画就直接显示出来了,内功心法也直接开始修炼了(浏览器会立即下载并执行这个资源)。

    比如,<script src="script.js"></script>,这里的src就是告诉浏览器,去这个地址把脚本文件下载下来,并且立即执行它。这就是为什么我们通常把script标签放在body底部的原因之一,因为脚本的下载和执行会阻塞页面的渲染。

总结:

简单来说,href是“引用”,它建立的是一种链接关系,浏览器可以继续处理当前页面,需要时再去获取链接的资源。而src是“引入”,它直接把资源“搬”过来,浏览器必须等待资源加载并执行完毕后才能继续处理后续内容。理解了这一点,你就能更好地优化网页的加载性能啦!

⏳ script标签的defer和async属性:让你的网页飞起来!

面试官:你知道script标签的defer和async属性吗?它们有什么作用?

你:嗯...好像是和脚本加载有关的...(内心OS:这俩兄弟又来搞事情了!)

这两个属性啊,就像是给你的JavaScript脚本开了“外挂”,让它们在不阻塞页面渲染的情况下加载和执行。但它们俩的“外挂”方式又有点不同。

image.png

其中蓝色代表js脚本网络加载时间,红色代表js脚本执行时间,绿色代表html解析。

通俗解释:

想象一下,你正在看一场精彩的电影(页面渲染),突然有人给你送外卖(加载JS脚本)。

  • 没有defer和async: 外卖小哥直接冲进电影院,让你暂停电影,等他把外卖送完你才能继续看。这体验,简直了!
  • defer: 外卖小哥很有礼貌,他会在电影放映结束后,等你电影看完了再把外卖送给你。这样你就能 uninterrupted 地看完电影了。
  • async: 外卖小哥更“自由”,他会在电影放映的同时,把外卖送到你手上。你可以在看电影的同时吃外卖,两不耽误!但要注意,如果外卖小哥送的太快,你可能还没准备好餐具呢!

代码解释:

<!-- 没有defer和async,会阻塞HTML解析和渲染 -->
<script src="script.js"></script>

<!-- defer,脚本会在HTML解析完成后,DOMContentLoaded事件触发前执行 -->
<script src="script.js" defer></script>

<!-- async,脚本会异步加载,加载完成后立即执行,不保证执行顺序 -->
<script src="script.js" async></script>

总结:

  • defer:适合那些需要操作DOM,并且对执行顺序有要求的脚本。
  • async:适合那些独立性强,不依赖DOM,且对执行顺序没有要求的脚本,比如统计代码。

合理使用这两个属性,能让你的网页加载速度“蹭蹭蹭”往上涨,用户体验也更好哦!

🎨 第二章:CSS和JS的“最佳位置”

🔧 CSS的link标签为什么放在head头部?

面试官:为什么我们通常把CSS的link标签放在head标签里?

你:为了让页面样式尽快生效...(内心OS:这还用问吗?)

没错,就是为了让样式尽快生效!但更深层次的原因,是为了避免“FOUC”(Flash Of Unstyled Content),也就是“无样式内容闪烁”。

通俗解释:

想象一下,你正在打扮准备出门。CSS就像是你的衣服。如果你先把衣服穿好再出门,那肯定是美美的。但如果你先出门,然后在大街上再一件一件地穿衣服,那画面...emmm,有点辣眼睛吧?

把CSS放在head里,就相当于你先穿好衣服再出门,这样用户一打开网页,就能看到美美的样式,不会出现先看到“裸奔”的网页,然后再突然穿上衣服的尴尬情况。

总结

  • link标签放在head标签中

    • 用户访问网站时,代码是从上往下解析的,正常展示页面内容的样式,提高用户体验

    • 放在 html 结构底部时,加载页面会出现 html 结构混乱的情况

🚀 JS的script标签为什么放在body底部?

面试官:那JS的script标签为什么又建议放在body底部呢?

你:为了不阻塞页面渲染...(内心OS:这俩问题是连环炮啊!)

这和我们前面提到的deferasync有点类似,主要原因也是为了避免阻塞页面渲染,以及确保JS能够正确操作DOM。

通俗解释:

还是拿看电影举例。JS就像是电影里的特效。如果你在电影还没开始放映的时候,就让特效师把所有特效都准备好,那电影肯定要等很久才能开场。但如果你让特效师在电影放映到需要特效的时候再准备,那电影就能流畅地播放了。

把JS放在body底部,就相当于让特效师在电影放映到需要特效的时候再准备。这样,浏览器可以先渲染页面的HTML和CSS,让用户尽快看到页面的基本内容,然后再加载和执行JS脚本。如果JS脚本需要操作DOM元素,放在底部也能确保DOM元素已经加载完成,避免出现“找不到元素”的错误。

总结

  • script标签放在body结束标签之前

    • JS脚本在下载和执行期间会阻止 html 解析

    • 把 script 标签放在底部,保证 html和css 首先完成解析之后再加载 JS 脚本

    • script 标签加上 defer 属性时,可以放在 head 标签中 (async)

  <script defer ></script> 

🌐 第三章:浏览器渲染的“奇妙之旅”

🔄 从输入URL到页面展示:浏览器都经历了啥?

面试官:请你详细描述一下,从你在浏览器地址栏输入一个URL,到最终页面展示出来,这中间都发生了什么?

你:这...这可太长了...(内心OS:这简直是前端界的“史诗级”问题!)

这个问题啊,就像是问你从家到公司,中间都经历了哪些交通工具、哪些路口、哪些红绿灯。它涵盖了网络、浏览器、操作系统等多个方面的知识,是检验你前端基础功底的“试金石”!

通俗解释:

想象一下,你是个“吃货”,想去一家网红餐厅(服务器)吃饭。你首先要知道餐厅的地址(URL),然后通过导航(DNS解析)找到餐厅的具体位置。接着,你得和餐厅建立联系(TCP连接),告诉他们你要点什么菜(HTTP请求)。餐厅收到你的订单后,开始为你准备美食(服务器处理)。最后,美食送到你面前,你开始大快朵颐(浏览器渲染)。

详细步骤:

  1. DNS解析: 你输入的URL会被解析成IP地址,就像导航把餐厅地址转换成具体的经纬度。
  2. TCP连接: 浏览器和服务器之间建立TCP连接,就像你和餐厅之间打通了电话,可以开始点菜了。
  3. HTTP请求: 浏览器向服务器发送HTTP请求,告诉服务器它想要什么资源(HTML、CSS、JS、图片等)。
  4. 服务器处理: 服务器收到请求后,根据请求内容返回相应的资源。
  5. 浏览器渲染: 浏览器收到资源后,开始解析HTML、CSS、JS,并最终将页面展示出来。这个过程又分为几个小步骤:
    • 解析HTML,生成DOM树: 浏览器把HTML代码翻译成它能理解的“骨架”。
    • 解析CSS,生成CSSOM树: 浏览器把CSS代码翻译成它能理解的“衣服”。
    • 构建渲染树(Render Tree): DOM树和CSSOM树结合,生成带有样式信息的渲染树。渲染树只包含需要显示的节点。
    • 布局(Layout/Reflow): 浏览器计算渲染树中每个节点的位置和大小。
    • 绘制(Painting): 浏览器将渲染树的每个节点绘制到屏幕上。

这个过程是不是很“奇妙”?每一步都环环相扣,才能最终呈现出你看到的精美网页!

📱 第四章:移动设备适配的“秘密武器”

📐 viewport:让你的网页在手机上也能“美美哒”

面试官:在不同移动设备下,你的网页内容是如何正常展示的?

你:用响应式布局...(内心OS:这不就是那个meta viewport吗?)

没错,响应式布局是关键,而viewport就是实现响应式布局的“秘密武器”之一!

image.png

通俗解释:

想象一下,你有一张很大的画(网页),想在不同大小的相框(手机屏幕)里展示。如果相框太小,画就显示不全。viewport就像是一个“魔法相框”,它可以根据你手机屏幕的大小,自动调整画的显示比例,让你的画在任何相框里都能完整、美观地展示出来。

总结

通常,我们会在HTML的<head>标签中添加如下meta标签来配置viewport

<meta name="viewport" content="width=device-width, initial-scale=1.0">
  • width=device-width:将视口宽度设置为设备的物理宽度。这样,网页的宽度就会和设备的屏幕宽度一致。
  • initial-scale=1.0:设置初始缩放比例为1.0。这意味着网页在加载时不会被放大或缩小。

除了这两个常用的属性,viewport还有其他一些属性:

  • height:视口的高度。
  • minimum-scale:允许用户缩放的最小比例。
  • maximum-scale:允许用户缩放的最大比例。
  • user-scalable:是否允许用户缩放页面(yes/no)。

合理配置viewport,能让你的网页在各种移动设备上都能拥有良好的用户体验!

🧠 第五章:DOM, BOM, JavaScript:前端的“三剑客”

⚔️ DOM, BOM, JavaScript:它们到底有啥区别?

面试官:请你详细描述一下DOM、BOM和JavaScript的区别及使用场景。

你:这...这三个不是一起用的吗?(内心OS:这回真要放大招了!)

它们就像是前端的“三剑客”,各自有各自的职责,但又紧密协作,共同完成了网页的各种交互和动态效果。

通俗解释:

想象一下,你正在玩一个乐高积木(网页)。

  • DOM(Document Object Model): 就像是乐高积木的“说明书”,它把网页的结构(HTML元素)抽象成一个对象模型,让你可以通过JavaScript来操作这些积木,比如添加新的积木、改变积木的颜色、删除积木等。
  • BOM(Browser Object Model): 就像是乐高积木的“工具箱”,它提供了与浏览器窗口进行交互的对象,比如你可以通过BOM来获取浏览器窗口的大小、控制浏览器的前进后退、弹出提示框等。
  • JavaScript: 就像是你的“双手”,你通过JavaScript来阅读“说明书”(DOM),使用“工具箱”(BOM),最终完成乐高积木的搭建和玩耍。

代码解释:

DOM的使用:

// 获取元素
const myParagraph = document.getElementById('myParagraph');

// 修改元素内容
myParagraph.textContent = '我被JavaScript修改了!';

// 修改元素样式
myParagraph.style.color = 'red';

// 创建新元素并添加到页面
const newDiv = document.createElement('div');
newDiv.textContent = '我是新创建的div!';
document.body.appendChild(newDiv);

BOM的使用:

// 弹出提示框
alert('Hello, BOM!');

// 获取浏览器窗口宽度
console.log('浏览器窗口宽度:' + window.innerWidth);

// 跳转到新的URL
window.location.href = 'https://www.google.com';

// 存储数据到本地存储
localStorage.setItem('username', '前端小能手');

// 返回上一页
history.back();

总结:

  • DOM: 操作网页内容(HTML元素)。
  • BOM: 操作浏览器窗口。
  • JavaScript: 连接DOM和BOM,实现网页的动态交互。

这“三剑客”紧密配合,才能让我们的网页变得生动有趣!

🌟 额外加餐:面试官的“送命题”

🔍 SEO优化:让你的网页被更多人看到!

面试官:你对SEO优化有什么了解?

你:就是让我的网页在搜索引擎里排名靠前...(内心OS:这可不是我的专业啊!)

虽然SEO优化更多是后端和运维的活儿,但作为前端,我们也能为SEO贡献一份力量!

通俗解释:

想象一下,你的网页就像是一个小商店。SEO优化就是给你的商店做广告,让更多的人知道你的商店,并且在搜索的时候能找到你的商店。作为前端,我们可以把商店的招牌(标题)、商品介绍(meta描述)写得更清楚,让搜索引擎更容易理解你的商店是卖什么的。

前端能做的SEO优化:

  • 语义化HTML: 使用正确的HTML标签来表示内容,比如用<h1>表示标题,<p>表示段落,<ul>表示列表等。这能让搜索引擎更好地理解你的网页结构和内容。

  • meta标签:<head>标签中添加meta标签,提供网页的元信息,比如关键词、描述等。

    <meta name="keywords" content="前端, 面试, HTML, CSS, JavaScript">
    <meta name="description" content="一篇关于前端基础知识的掘金博客,帮助你轻松应对面试。">
    
  • 标题(title标签): 确保每个页面的title标签都独一无二,并且包含关键词。

    <title>前端面试不慌张:HTML基础知识全掌握</title>
    

🔢 HTTP状态码:网页的“表情包”

面试官:你知道常见的HTTP状态码有哪些吗?它们分别代表什么意思?

你:200是成功,404是找不到...(内心OS:这可太多了,背不过啊!)

HTTP状态码就像是网页的“表情包”,每个数字都代表着服务器对你请求的不同回应。了解它们,能让你更好地排查网页问题。

通俗解释:

想象一下,你给朋友发消息。HTTP状态码就是你朋友给你的回复。

  • 2xx(成功): 朋友回复“收到!”、“好的!”、“没问题!”。表示你的请求成功了,服务器也成功处理了。
    • 200 OK:一切正常,请求成功。
  • 3xx(重定向): 朋友回复“我搬家了,去新地址找我!”。表示你需要去另一个地方才能找到资源。
    • 301 Moved Permanently:永久重定向,资源被永久移动到新地址。
    • 302 Found:临时重定向,资源暂时在另一个地址。
  • 4xx(客户端错误): 朋友回复“你是不是发错人了?”、“你说的啥我听不懂!”。表示你的请求有问题,服务器无法处理。
    • 400 Bad Request:请求语法错误,服务器无法理解。
    • 401 Unauthorized:未授权,你需要登录才能访问。
    • 403 Forbidden:禁止访问,你没有权限访问该资源。
    • 404 Not Found:找不到资源,你请求的页面不存在。
  • 5xx(服务器错误): 朋友回复“我生病了,今天不营业!”。表示服务器出问题了,无法处理你的请求。
    • 500 Internal Server Error:服务器内部错误,服务器出故障了。
    • 502 Bad Gateway:网关错误,服务器作为网关或代理时,从上游服务器收到无效响应。
    • 504 Gateway Timeout:网关超时,服务器作为网关或代理时,没有及时从上游服务器收到响应。

记住这些“表情包”,你就能更好地和服务器“沟通”啦!

总结

好啦,今天的面试知识分享就到这里啦!希望通过这篇博客,能让你对前端的基础知识有更深入的理解。记住,基础不牢,地动山摇!只有把基础打扎实了,才能在前端的道路上越走越远!

如果你觉得这篇博客对你有帮助,别忘了点赞、收藏、转发哦!咱们下期再见!👋

🎯 代码演示效果

为了让大家更直观地理解这些前端基础知识,我特意制作了一个交互式演示页面。让我们来看看实际的运行效果:

🖼️ 效果演示:

轻映录屏 2025-07-28 23-19-16.gif

💻 完整代码示例

如果你想亲自体验这些效果,可以将以下代码保存为HTML文件:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>前端基础知识演示</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 20px;
            background-color: #f5f5f5;
        }
        .container {
            max-width: 800px;
            margin: 0 auto;
            background: white;
            padding: 20px;
            border-radius: 8px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
        }
        .demo-section {
            margin: 20px 0;
            padding: 15px;
            border: 2px solid #e0e0e0;
            border-radius: 5px;
        }
        .demo-title {
            color: #333;
            border-bottom: 2px solid #007acc;
            padding-bottom: 5px;
        }
        .viewport-demo {
            border: 2px solid #ff6b6b;
            padding: 10px;
            text-align: center;
            background: linear-gradient(45deg, #ff6b6b, #4ecdc4);
            color: white;
            border-radius: 5px;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>🚀 前端基础知识演示</h1>
        
        <div class="demo-section">
            <h2 class="demo-title">⚔️ DOM操作演示</h2>
            <p id="myParagraph">这是一个段落,点击按钮看变化!</p>
            <button onclick="changeText()">改变文字</button>
            <button onclick="changeColor()">改变颜色</button>
        </div>

        <div class="demo-section">
            <h2 class="demo-title">🧠 BOM操作演示</h2>
            <button onclick="showWindowInfo()">显示窗口信息</button>
            <button onclick="testLocalStorage()">测试本地存储</button>
            <div id="bomResult">点击按钮查看BOM操作结果</div>
        </div>
    </div>

    <script>
        function changeText() {
            const paragraph = document.getElementById('myParagraph');
            paragraph.textContent = '我被JavaScript修改了!🎉';
        }

        function changeColor() {
            const paragraph = document.getElementById('myParagraph');
            const colors = ['red', 'green', 'blue', 'purple', 'orange'];
            const randomColor = colors[Math.floor(Math.random() * colors.length)];
            paragraph.style.color = randomColor;
        }

        function showWindowInfo() {
            const result = document.getElementById('bomResult');
            result.innerHTML = `
                <strong>窗口信息:</strong><br>
                宽度: ${window.innerWidth}px<br>
                高度: ${window.innerHeight}px
            `;
        }

        function testLocalStorage() {
            localStorage.setItem('前端小能手', '掘金博客');
            const value = localStorage.getItem('前端小能手');
            const result = document.getElementById('bomResult');
            result.innerHTML = `
                <strong>本地存储测试:</strong><br>
                存储的值: ${value}<br>
                存储时间: ${new Date().toLocaleString()}
            `;
        }
    </script>
</body>
</html>

这个演示页面完美地展示了我们在博客中讨论的所有概念。通过实际的代码和交互效果,相信你对前端基础知识有了更深入的理解!