HTML5 的新特性有哪些?
简约版本:
"HTML5 新特性主要体现在六个方面:
第一,语义化标签,比如 header、footer、nav 等,让页面结构更清晰;
第二,表单增强,新增了 date、email 等类型和 placeholder、required 等属性;
第三,多媒体支持,提供了 audio 和 video 标签,不再依赖 Flash;
第四,图形绘制,有 canvas 和 svg;
第五,本地存储,提供了 localStorage 和 sessionStorage;
第六,一些新的 API,比如 WebSocket 实时通信、Web Worker 多线程、地理定位、拖拽 API 和 History API 等。
总体来说,HTML5 更加语义化、增强了交互体验,也提高了性能和可用性。"
详细版本:
主要分为 语义化标签、表单增强、多媒体支持、图形绘制、本地存储、API 六大类:
-
语义化标签
-
新增结构标签:
header
、footer
、nav
、section
、article
、aside
、main
-
作用:提升页面语义,利于 SEO 和可访问性
-
-
表单增强
-
新的表单控件:
date
、email
、url
、number
、range
、color
、search
-
新的属性:
required
、placeholder
、pattern
、autofocus
-
-
多媒体支持
-
原生音视频标签:
<audio>
、<video>
-
支持多种格式,不依赖 Flash
-
-
图形绘制
-
canvas
:支持 2D 图形绘制 -
svg
:矢量图形支持
-
-
本地存储
-
localStorage
:长期存储,容量比 cookie 大 -
sessionStorage
:会话级存储
-
-
新的 API
-
地理定位 :
navigator.geolocation
-
拖放 API :
drag & drop
-
Web Worker:多线程处理
-
WebSocket:双向实时通信
-
History API:控制浏览器历史记录
-
ARIA / 无障碍开发面试题 & 答案
Q1. 什么是 ARIA?
ARIA(Accessible Rich Internet Applications)是一组 HTML 属性,主要以 aria-
开头。它的作用是帮助辅助技术(比如屏幕阅读器)理解页面结构和交互状态。
在现代前端中,我们经常用自定义组件(比如用 div
模拟按钮),这些元素本身没有语义,屏幕阅读器读不懂。ARIA 就是用来补充语义信息,让页面对残障用户更加友好。
👉 可以补充一句:ARIA 不会改变视觉效果,只影响辅助技术的理解。
Q2. 常见的 ARIA 属性有哪些?举例
**1.角色(role):**定义元素的语义角色,帮助辅助技术识别它是什么。
-
banner
(页面头部) -
navigation
(导航区域) -
main
(主要内容) -
complementary
(补充内容) -
contentinfo
(页脚信息) -
search
(搜索区域) -
button
(按钮) -
checkbox
(复选框) -
radio
(单选按钮) -
tab
(选项卡) -
tabpanel
(选项卡面板) -
tooltip
(提示信息) -
dialog
(对话框) -
article
(文章) -
heading
(标题) -
list
(列表) -
listitem
(列表项) -
table
(表格) -
等等
2. 状态/属性(aria-*):描述元素当前状态,比如展开/选中/禁用等。
-
aria-label
:给元素添加描述信息。 -
aria-hidden
:让读屏器忽略某个元素。 -
aria-expanded
:表示菜单是否展开。 -
aria-checked
:复选框是否选中。 -
aria-live
:提示动态区域,读屏器会自动播报内容更新。
html
<div role="button" aria-pressed="false" tabindex="0">
点我
</div>
//role="button" → 让它被识别为按钮
//tabindex="0" → 允许键盘 Tab 聚焦
//aria-pressed="false" → 状态(未按下)
Q3. 开发无障碍应用时,ARIA 和语义化 HTML 有什么关系?
最佳实践是 优先使用语义化 HTML 标签 (比如 <button>
、<nav>
、<header>
),因为浏览器和读屏器天然支持。
ARIA 是 补充手段 ,当我们用自定义组件(比如 div
写的按钮)时,再用 role
和 aria-*
属性来增强可访问性。
一句话总结:能用原生标签就用原生,实在不行才用 ARIA。
Q4. 如何让自定义组件可访问?
- 给组件加
role
(补充语义)。 - 用
aria-*
属性描述状态(比如展开、禁用、选中)。 - 确保 键盘可操作 ,加
tabindex="0"
并监听 Enter/Space 键事件。 - 动态内容要用
aria-live
或role="alert"
提示用户。
👉 这样屏幕阅读器和键盘用户都能正常使用。
Q5. 在实际工作中,你做过哪些可访问性优化?
参考回答:(随便挑 2--3 点说)
-
用语义化标签代替纯
div
/span
,比如<button>
。 -
给图片加
alt
,给图标加aria-hidden="true"
。 -
自定义组件时,补充
role
和aria-*
属性。 -
处理键盘可访问性(Tab 聚焦、Enter/Space 触发)。
-
动态提示(比如表单报错)用
aria-live
让读屏器播报。
Q6. ARIA 有什么使用原则?
参考回答:
-
能用 HTML 原生语义就用原生,不要过度依赖 ARIA。
-
只在必要时添加,避免属性过多导致读屏器混乱。
-
测试可访问性:实际用屏幕阅读器(NVDA、VoiceOver)和键盘来测试。
CSS 相关问题
1. CSS 选择器的优先级是怎么计算的?
👉 内联样式 > ID 选择器 > 类 / 属性 / 伪类选择器 > 标签选择器 > 通配符 > 继承 > 浏览器默认样式。
数值记忆法:行内(1000) > ID(100) > 类/伪类(10) > 标签/伪元素(1)。
2. 标准盒模型和 IE 盒模型有什么区别?
👉 标准盒模型:width
只包含 content,不含 padding 和 border。
👉 IE 盒模型:width
包含 content + padding + border。
css
元素总宽度 = content + padding + border + margin
元素总高度 = content + padding + border + margin
box-sizing: content-box; /* 标准盒模型(默认) */
box-sizing: border-box; /* 怪异盒模型 */
3.如何创建响应式布局?
👉 媒体查询(Media Queries):根据不同屏幕宽度设置不同的样式。
css
/* 默认样式:移动端优先 */
.container { font-size: 14px; }
/* 平板端 */
@media (min-width: 768px) {
.container { font-size: 16px; }
}
/* PC 端 */
@media (min-width: 1200px) {
.container { font-size: 18px; }
}
👉 流式布局(Fluid Layout):使用百分比 %
、视口单位 vw/vh
、弹性单位 em/rem
等,而不是固定 px
。
👉 弹性盒子(Flexbox):用 flex
让子元素在父容器中自动适应。
👉网格布局(CSS Grid):Grid 天生适合响应式布局。 自动根据屏幕宽度决定列数。
css
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 20px;
}
👉响应式图片 / 媒体:使用 max-width: 100%
让图片不超出容器。
👉移动端适配(viewport 设置):确保在不同设备上缩放正常。
css
<meta name="viewport" content="width=device-width, initial-scale=1.0">
移动端优先 是主流做法:先写小屏,再通过媒体查询适配大屏。
4. position 的值有哪几种?区别是什么?
-
static:默认定位,不受 top/left 影响。
-
relative:相对自身定位,占据原位置。
-
absolute:相对最近的非 static 祖先定位。
-
fixed:相对浏览器窗口定位,不随滚动条移动。
-
sticky:结合 relative 和 fixed,根据滚动位置切换。
5. z-index 为什么有时不起作用?
-
没有定位属性
-
z-index
只在元素设置了定位(position: relative | absolute | fixed | sticky
)时才生效。 -
如果是
position: static
(默认),z-index
不会起作用。
-
-
层叠上下文(Stacking Context)影响
-
元素所在的层叠上下文会限制它的
z-index
效果。 -
每个层叠上下文内部的元素
z-index
只在自己"上下文"里比较,无法跨层叠上下文提升。 -
触发层叠上下文的情况(常见):
-
设置了
position
且z-index
值不是auto
; -
设置了
opacity < 1
; -
设置了
transform
、filter
、perspective
、clip-path
等属性; -
设置了
isolation: isolate
。
-
-
-
父子关系影响
- 子元素的
z-index
受限于父元素所在的层叠上下文,即使子元素z-index
再大,也不会覆盖在父元素所在层叠上下文之外的兄弟元素之上。
- 子元素的
-
浏览器默认层叠顺序
-
如果
z-index
相同或没设置,浏览器会按照以下顺序叠放:-
背景和边框(最底层)
-
负
z-index
元素 -
块级元素(按 HTML 顺序)
-
浮动元素
-
行内元素(按 HTML 顺序)
-
正
z-index
元素(数值越大越靠上)
-
-
6.如何实现水平垂直居中?
- 使用 Flex 布局(推荐 ✅)
css
.parent {
display: flex;
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
}
.child {
width: 100px;
height: 100px;
}
- 使用 Grid 布局
css
.parent {
display: grid;
place-items: center; /* 水平 + 垂直居中 */
}
- 绝对定位 + transform
css
.parent {
position: relative;
}
.child {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
- 绝对定位 + margin auto
css
.parent {
position: relative;
}
.child {
position: absolute;
top: 0; bottom: 0;
left: 0; right: 0;
margin: auto;
width: 100px;
height: 100px;
}
- 传统方法:表格布局 / line-height
css
//第一。表格法(适合文字/小组件):
.parent {
display: table-cell;
text-align: center; /* 水平 */
vertical-align: middle; /* 垂直 */
}
// 第二。line-height 法(适合单行文本):
.parent {
height: 100px;
line-height: 100px; /* 设置等于高度 */
text-align: center;
}
**7.**什么是 BFC?有什么作用?
👉定义
-
BFC 全称 Block Formatting Context(块级格式化上下文)。
-
它是页面中的一个独立渲染区域,内部元素的布局不会影响到区域外部。
👉如何触发 BFC(常见几种方式)
-
设置
float
值(left
/right
,但不是none
)。 -
设置
position
为absolute
/fixed
。 -
设置
display
为inline-block
、table-cell
、flex
、grid
等。 -
设置
overflow
为hidden
、auto
、scroll
。
👉 BFC 的特性 / 作用
-
清除浮动:父元素触发 BFC 后,可以包含子元素的浮动,不会出现高度塌陷。
-
避免外边距重叠(margin collapse) :同一个 BFC 内的块级元素上下
margin
会重叠,不同 BFC 之间则不会。 -
隔离作用:BFC 区域和外部独立,内部元素不会影响外部布局。
-
自适应两栏布局:利用 BFC 可以实现一边浮动一边自适应。
👉 常见应用场景
-
✅ 清除浮动问题
-
✅ 阻止
margin
合并 -
✅ 实现多栏布局(左侧固定宽度,右侧自适应)
JavaScript 作用域 & 闭包
1. 什么是作用域?有哪些类型?
作用域(Scope)是指程序中变量和函数的可访问范围。
JavaScript 的作用域类型主要有:
-
全局作用域:在代码最外层声明的变量和函数,整个程序都可以访问。
-
函数作用域:每个函数调用时都会创建自己的作用域,函数内部定义的变量只能在函数内部访问。
-
块级作用域 :
let
和const
声明的变量只在代码块{}
内有效,例如 if、for 中。
👉 JavaScript 采用 词法作用域(在函数定义时就决定了作用域,而不是运行时)。
2. 什么是作用域链?
当访问一个变量时,JavaScript 引擎会:
-
先在当前作用域查找
-
如果找不到,就沿着外层作用域逐级向上查找
-
直到全局作用域,如果还没找到,就抛出
ReferenceError
这种 逐级查找的链条 就叫 作用域链 。
👉 本质:函数持有外部作用域的引用。
3. 什么是执行上下文(Execution Context)?
执行上下文是 JavaScript 代码运行时的环境。
每次执行一段代码时,都会创建一个执行上下文,包括:
-
变量环境(var 声明的变量、函数声明)
-
词法环境(let、const 声明的变量)
-
this 绑定(当前执行环境的 this 指向)
执行上下文分为三类:
-
全局上下文(页面首次运行时创建,只有一个)
-
函数上下文(每次调用函数时都会创建)
-
eval 上下文(eval 代码执行时创建,不推荐使用)
4. 什么是变量提升?
JavaScript 在代码执行前,会先进行"预编译"阶段:
-
var
声明的变量会提升到作用域顶端,默认值是undefined
。 -
函数声明(function declaration)会整体提升,可以在声明前调用。
-
let
和const
也会提升,但存在 暂时性死区(TDZ),在声明前使用会报错。
css
console.log(a); // undefined
var a = 10;
console.log(b); // ReferenceError
let b = 20;
5.this 在不同场景下的指向是什么?
-
普通函数调用 → 在非严格模式下指向全局对象(
window
),严格模式下是undefined
。 -
对象方法调用 → 指向调用该方法的对象。
-
构造函数调用(new) → 指向新创建的实例对象。
-
显式绑定 → 使用
call
、apply
、bind
可以手动指定 this。 -
箭头函数 → 没有自己的 this,继承外层作用域的 this。
6. 什么是闭包?
闭包是指一个函数与其周围的词法环境(变量和状态)的绑定。通过闭包,函数可以访问其外部作用域中的变量,即使在外部函数执行结束后,这些变量依然可以被内部函数访问和使用。
闭包的本质是函数与其定义时的作用域环境的结合。当一个函数返回另一个函数时,返回的内部函数会保留对外部函数作用域的引用,从而形成闭包。
条件(记三个字:函数 + 引用)
-
必须有 函数嵌套
-
内部函数 用到了外部变量
-
外部函数执行完,但变量 仍被引用
作用:
-
数据持久化:能够让某些变量长期保存在内存中,实现状态的记忆。
-
封装与私有化:利用闭包,可以模拟私有变量,避免外部随意修改。
-
函数式编程:闭包是实现回调函数、高阶函数、函数工厂等的重要基础。
缺点:
(1)容易在循环中出 bug(var
导致所有闭包共享同一个变量)
javascript
(1)循环里的闭包问题
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 1000);
}
// 输出:3 3 3
原因:var i 是同一个函数作用域,闭包引用的是同一个 i
解决方法:
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 1000);
}
// 输出:0 1 2
或者使用 IIFE(立即执行函数):
for (var i = 0; i < 3; i++) {
((i) => {
setTimeout(() => console.log(i), 1000);
})(i);
}
(2)内存泄漏
- 闭包持有外部函数的变量引用,如果使用不当,可能导致内存不能及时释放。
7. 为什么闭包会导致内存泄漏?
因为闭包会让外部函数的变量一直被引用,垃圾回收机制(GC)无法释放这部分内存。
解决方法:
-
在不需要闭包时,将其引用置为
null
-
避免过度使用闭包
8. 闭包的实际应用场景有哪些?
(1)封装私有变量
css
function Counter() {
let count = 0;
return {
inc: () => ++count,
dec: () => --count
};
}
(2)事件处理器(回调函数中访问外部变量)
(3)函数柯里化(currying)
javascript
function add(a) {
return function(b) {
return a + b;
};
}
9. 什么是事件循环(Event Loop)?宏任务和微任务有什么区别?
JavaScript 是单线程的,采用 事件循环机制 来处理异步任务。
执行顺序:
-
先执行 同步代码(主线程)。
-
同步执行完后,检查 微任务队列(microtask queue),依次执行完。
-
微任务清空后,再执行一个 宏任务(macrotask)。
-
重复以上过程,形成循环。
常见宏任务(macrotask): setTimeout
、setInterval
、setImmediate
、I/O、UI 渲染。
常见微任务(microtask): Promise.then/catch/finally
、MutationObserver
、queueMicrotask
、process.nextTick(Node)
。
👉 口诀:先同步 → 再微任务 → 再宏任务。
10. 什么是原型和原型链?
-
原型(prototype) :
每个函数都有一个
prototype
属性,用于存放实例共享的方法和属性。 -
原型链 (Prototype Chain):
对象在查找属性时,会先在自己本身查找,如果没有,就沿着
__proto__
向上查找父级原型,直到Object.prototype
,再到null
停止。
javascript
function Person() {}
const p = new Person();
console.log(p.__proto__ === Person.prototype); // true
console.log(Person.prototype.__proto__ === Object.prototype); // true
👉 原型链的本质是 对象属性查找机制。
11. async / await 的底层原理是什么?
-
async/await
是 ES2017 引入的语法糖,用来写异步代码。 -
async
函数默认返回一个Promise
。 -
await
用来等待一个Promise
的结果,函数会"暂停"执行,等结果出来再继续。 -
👉 作用:让异步代码写起来更像同步代码,可读性更好。
底层原理:
-
async/await
是Promise
的语法糖,本质是基于 Promise + Generator 实现的。 -
await
会暂停函数的执行,把后续代码放进微任务队列,等Promise
完成后再继续执行。
👉 关键点:await
会把后续代码放到 微任务队列。
12. Promise 是什么?解决了什么问题?
-
Promise
是 ES6 引入的一种 异步编程的解决方案,用于表示一个可能在未来某个时间点才会完成的操作结果。 -
本质是一个 状态机 ,有三种状态:
pending
(进行中)、fulfilled
(已成功)、rejected
(已失败),且状态 不可逆。 -
Promise
提供了统一的.then/.catch/.finally
接口,使得我们可以通过链式调用来组织异步代码。
解决的问题:
(1)回调地狱(Callback Hell)
-
传统异步依赖多层嵌套回调,代码难以维护;
-
Promise
通过链式调用让异步逻辑更加扁平化、清晰。
(2)错误处理分散
-
回调模式下错误需要逐层处理;
-
Promise
支持 错误冒泡 ,集中用.catch
捕获异常。
(3)异步流程控制
Promise.all / race / allSettled / any
提供了强大的并发控制能力,方便管理多个异步任务。