常见面试问题
自适应布局中的 rem 是什么原理?
rem(root em)是css中一种相对长度单位,其核心原理是相对于跟元素(html)的字体大小进行缩放。
核心原理
rem的基准是根元素HTML的font-size
属性:
1 | html{ |
动态计算
所有使用rem的元素尺寸都会根据字体大小动态计算:
1 | .demo{ |
自适应关键
通过JS或媒体查询动态修改根字体大小,页面所有rem单位元素都会等比例缩放:
1 | //根据视口宽度动态设置根元素字体大小 |
工作流程
1. 设计稿基准
假设设计稿宽度750px,约定1rem = 设计稿100px
2. 设计根字体
1 | // 视口宽度375px的设备上: |
3. 元素尺寸转换
1 | /* 设计稿中200px宽的元素 */ |
4. 不同屏幕效果
设备宽度 | 跟字体大小 | 元素实际宽度 |
---|---|---|
375px | 50px | 2X50=100px |
对比其他单位
单位 | 基准 | 自适应能力 | 缺点 |
---|---|---|---|
rem | 根元素字体大小 | 🌟🌟🌟🌟🌟 | 需要动态计算根字体 |
em | 父元素字体大小 | 🌟🌟 | 嵌套层级影响计算 |
px | 固定像素 | 无法自适应 | |
vw | 视口宽度的1% | 🌟🌟🌟🌟 | 小屏幕显示内容可能过小 |
% | 父元素尺寸的百分比 | 🌟🌟🌟 | 依赖父级容器 |
对于CSS中盒模型的理解
盒模型是CSS布局中的核心概念,它描述了HTML元素在页面所占空间结构。每个元素都被视作一个矩形盒子。这个盒子包含以下四个部分:
- 内容区(
content
):- 最内层区域,包含元素的实际内容(如文本、图片等)。
- 大小由
width
和height
属性控制。
- 内边距(
padding
):- 位于内容区和边框之间的透明区域。
- 控制内容与边框之间的距离。
- 大小由
padding
及其相关属性(padding-left
、padding-right
、padding-top
、padding-bottom
)控制。
- 边框(
border
):- 包裹内容和内边距的
- 可以设置颜色,粗细,样式。
- 大小由
border
相关属性控制
- 外边距(
margin
):- 位于边框之外的透明区域。
- 控制当前元素与其他元素之间的距离。
- 大小由
margin
相关属性控制。
关键点:
- 总高度/宽度计算:
- 总宽度 =
width
+ 左(padding
、margin
、border
)+ 右(padding
、margin
、border
) - 总高度 =
height
+ 上(padding
、margin
、border
)+ 下(padding
、margin
、border
)
- 总宽度 =
- box
box-sizing
属性:这个属性决定了width
和height
属性具体定义的是哪一部分的尺寸。这里是理解盒模型的关键差异点:content-box
:默认(标准)盒模型:width
和height
只定义内容区的尺寸。- 元素的总宽度/高度需要加上
padding
,border
,margin
。
border-box
常用(IE怪异/现代推荐)盒模型:width
和height
定义了 内容区 + 内边距 + 边框 的总尺寸。- 元素的总宽度/高度 = width/height + margin。 padding 和 border 的宽度被包含在设定的 width/height 值内。
- 这使得布局计算更直观,是现在最常用的设置(通常用 * { box-sizing: border-box; } 全局设置)。
- 外边距折叠(Margin Collapsing): 垂直方向上相邻的两个块级元素的外边距有时会合并(折叠)成一个外边距,其大小等于两个外边距中的较大者。
总结:
盒模型是理解元素尺寸、间距和布局的基础。掌握内容区、内边距、边框、外边距的定义,以及 box-sizing 属性(尤其是 border-box)对元素最终尺寸的影响,对于精确控制页面布局至关重要。外边距折叠是另一个需要注意的特性,特别是在垂直布局时。
什么是变量提升?var
、let
、const
有什么区别?
var
:声明被提升到顶部,初始值为undefined
.1
2console.log(e) //undefined
var e = 1;let
和const
存在暂时性死区,在声明前访问会报错。1
2console.log(e) // RefrenceError
let e = 10;
如何确定this
指向
- 普通函数:
this
指向调用者。 - 箭头函数:
this
继承外部作用域。 - 显示绑定:
call
、apply
、bind
1
2
3const obj = { name: "Alice" };
function greet() { console.log(this.name); }
greet.call(obj); // "Alice"
解释事件循环、宏任务与微任务。
- 调用栈:同步代码执行。
- 任务队列:
- 宏任务:
setTimeout
、setinterval
、I/O
。 - 微任务:
Promise.then
、MutationObserver
、queueMicrotask
- 执行顺序:同步代码 → 微任务队列清空 → 宏任务。
- 宏任务:
Promise 如何解决回调地狱?async/await 的作用?
Promise链式调用
:1
2
3
4fetch(url)
.then(res => res.json())
.then(data => console.log(data))
.catch(err => console.error(err));async/await
以同步的方式写异步代码。1
2
3
4
5
6
7
8async function getData(){
try {
const res = await fetch(url);
const data = await res.json();
} catch (err) {
console.error(err);
}
}
列举常用的 ES6 特性。
- let/const、箭头函数、解构赋值。
- 模板字符串、默认参数、Rest/Spread 运算符。
- 模块化(import/export)、类(class)、Map/Set。
防抖和截流区别是什么?如何实现?
- 防抖:连续触发时,只执行最后一次。
1
2
3
4
5
6
7function debounce(fn, delay) {
let timer;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => fn(...args), delay);
};
} - 节流:固定时间间隔执行一次(如滚动事件)。
1
2
3
4
5
6
7
8
9
10function throttle(fn, interval) {
let lastTime = 0;
return (...args) => {
const now = Date.now();
if (now - lastTime >= interval) {
fn(...args);
lastTime = now;
}
};
}
如何解决跨域问题
- CORS:服务器设置响应头(Access-Control-Allow-Origin)。
- JSONP:通过
<script>
标签跨域(仅 GET 请求)。 - 代理服务器:前端请求同域代理,代理转发请求。
- WebSocket:不受同源策略限制。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 CCの日记!
评论