前端的面试小题尝一尝!

270 阅读10分钟

1 HTML

1.1 doctype的意义是什么?

doctype的作用

  • 让浏览器以标准模式渲染
  • 让浏览器知道元素的合法性

很久很久以前,故事发生在一个科技尚未进步的年代,那个时候的IE有一些自己的渲染模式,最典型的就是盒子模型。如果你设置一个元素的width:200px,渲染出来的内容不一定是200px宽的,他还包含了paddingborder,假如说padding10px,那么你的内容实际上只有180px宽,这就是以前经常存在的一个问题。

但是标准的盒子模型,设置宽度为200px的时候是不包含padding的,所以整个盒子可能是220px宽,这就产生了兼容的问题,为了解决这个问题,出现了doctype,这个东西就让浏览器用标准模式渲染。

另外,doctype让浏览器能够知道元素的合法性,如果使用一个html4doctype,一些元素的写法如果不合法的话,比如元素没有闭合,浏览器就会“知道”。当然,浏览器知道了也不会怎么样,最终还是会进行容错处理,正常渲染。

浏览器:你不在意的细节毁了我好多的温柔····QAQ

1.2 HTML、XHTML和HTML5的关系

  • HTML属于SGML的一个应用
  • XHTML属于XML,是对HTML进行XML严格化的结果
  • HTML5不属于任何一种,是自己的一套规范,相比于XHTML更加宽松

1.3 HTML5有什么变化?

  • 新的语义化元素:section header footer aside
  • 表单增强:新的元素、表单验证
  • 新的API(离线、音视频、图形、实时通信、本地存储、设备能力)
  • 分类和嵌套的变更

1.4 em和i有什么区别?

  • em是语义化的标签,表强调
  • i标签是纯样式的标签,表斜体
  • i在HTML5中不建议用到,i更多的用于图标icon

1.5 语义化的意义是什么?

  • 开发者更容易理解
  • 机器更容易理解结构(搜索、读屏、软件)
  • 有助于SEO(搜索引擎优化)
  • semantic microdata

1.6 那些元素可以自闭合?

  • 表单元素input
  • 图片 img
  • br hr
  • meta link

1.7 HTML和DOM的关系

  • HTML是“死”的,实际上就是一堆字符串,是个文本文档
  • DOM是由HTML解析出来的,是“活”的
  • JS维护的是DOM

1.8 property和attribute的区别?

都是属性的意思

  • 实际上property是特性,attribute才是属性
  • attribute是“死”的
  • property是“活”的
  • 简单来说,attribute一般是写死的,通过一些方法能修改显示的值,动态修改的是property

1.9 form的作用有哪些?

  • 直接提交表单
  • 使用submit / reset按钮
  • 便于浏览器保存表单
  • 第三方库可以提取整体值
  • 第三方库可以进行表单验证

2 CSS

2.1 CSS在浏览器上的解析方式和性能?

如果有一个这样的结构body>div>a(class: hello),在写a标签的样式的时候,如果出现了这样的情况:.body div .hello,自然而然的想到,先找到body,再找到里面的div,再找div里面a标签的类名为 hello的a标签。

然而实际上不是这样的,浏览器的解析方式正好是反过来的,它会先找一个类名为hello的标签,再验证它是否有一个div祖先,再验证body。

即浏览器的解析方式是从右往左的

这是从性能的角度考虑的,如果从左往右,一个body的里面有很多个div,从几百个div里面找一个后代就很难,所以不采用这种方法~

2.2 图片3px问题

**现象:**img图片在div中,图片会把父元素向下大约撑3px的空隙左右。

**原因:**img在div中是类似于inline的元素,比如和文本在一块,默认的对其方式是和文本一样的,使用vertical-align:baseline即基线对齐,这时候就有了一个line-height,然而基线和底线还是有区别的,图片底线距离底线就有可能出现大约3px的距离。

解决办法:

  • 子元素img添加vertical-align:bottom
  • 子元素img添加display:block,这样可能让图片不单独在一行了,但是也是解决了间隙问题
  • 子元素img添加:float:;,父元素div添加:overflow:hidden,目的是解决父元素高度塌陷
  • 子元素img添加:margin-top:-3px
  • 给父元素div添加font-size:0line-hight:0

2.3 CSS样式的优先级

不同样式计算权重:

  • 1.第一优先级:!important,在属性后面直接添加,会覆盖页面内任何样式。
  • 2.第二优先级:内联样式,在HTML标签内直接加style
  • 3.计算权重:id选择器100,类、伪类和属性选择器10,标签选择器和伪元素选择器1. 注意,计算权重的时候没有进位,十一个类选择器也不会大于一个id选择器。
  • 另外一点,优先级相同的时候,写在后面的生效

2.4 雪碧图的作用

**雪碧图的实现:**使用background设置背景图,利用background-position定位,找到小图标,将图片上的图标合并,得到雪碧图。

作用:

  • 减少HTTP请求次数,提高加载性能
  • 有一些情况下可以减少图片大小。如果有一堆图片,他的调色板或者说它们里面可能出现的颜色基本一样的时候,图标合并后的图片大小可能比之前的要小一些。

2.5 自定义字体的使用场景

  • 宣传、品牌、banner等固定的文案
  • 字体图标

2.6 base64的使用

  • 用于减少HTTP的请求
  • 适用于小图片
  • base64的体积是原图的4/3

2.7 如何美化checkebox

  • label[for]和id
  • 隐藏原生input
  • :checked + label

2.8 inline-block清除间隙问题

  • 设置父元素的font-size:0,如果子元素中需要文字,在各自的样式中分别设置字体大小即可
  • 删除HTML代码中的换行,直接在一个div结束后接着写,或者在两个div中间加一个注释

2.9 实现两栏、三栏布局的方法

  • 表格布局,display:table/table-row/table-cell
  • float+margin布局,注意float清除浮动
  • inline-block布局,注意清除间隙
  • flex-box布局,兼容性一般

2.10 position:absolute/fixed 的区别

  • position:absolute是相对最近一个absolute/abstract相对定位
  • position:fixed是相对屏幕,或者说viewport相对定位

2.11 清楚浮动相关问题

**产生原因:**浮动元素不会占据父元素的布局空间,有可能浮动元素会超出父元素,从而影响其他的元素布局

**解决办法:**让盒子负责自己的布局

  • overflow:hidden(auto)
  • ::after(clear:both)

2.12 适应移动端设备

  • 设置viewport
  • rem/viewport/media query
  • 设计:隐藏、折行、自适应

2.13 如何用一个div画一个xxx

  • box-shadow无限投影
  • ::before
  • ::after

2.14 如何产生不占空间的边框

  • box-shadow : 不设置模糊,只设置一个阴影即可
  • outline

2.15 如何实现一个圆形

  • border-radius: 50%

**关于IOS的圆角矩形:**用绘图之类的软件到处svg图,然后用clip-path:(svg)裁剪

2.16 如何实现半圆、扇形和一些其他奇奇怪怪的图形?

  • border-radius组合
  • 有无边框:边框影响圆角的大小,因为边框的宽度也计算在内了
  • 边框粗细:原因同上
  • 圆角半径:四个角设置不同的半径,可以实现奇奇怪怪的效果

2.17 如何实现背景图居中显示/不重复/改变大小

  • background-position
  • background-repeat
  • background-size(cover/contain)

2.18 如何平移/放大一个元素

  • transform:translateX(100px)
  • transform:scale(2)
  • 注意transform是不包含动画的,并没有绝对挂钩

2.19 CSS动画的实现方式有几种?

  • transition补间动画/过渡动画
  • keyframes(animation)关键帧动画

2.20 过渡动画和关键帧动画的区别?

  • 过渡动画需要有状态变化
  • 关键帧动画不需要状态变化,这要设置transition即可
  • 关键帧动画相对更精细

2.21 如何实现逐帧动画

  • 利用keyframes关键帧动画定义每一帧
  • 核心内容是利用steps去掉补间,让一帧一帧变化

2.22 CSS动画的性能

  • **CSS动画性能不坏:**CSS动画的性能不能说是最好的,但是一定写不出性能非常差的CSS动画,如果使用CSS写出来的动画性能非常差,只能说明这个动画过于复杂,用JS也写不出更好的性能了
  • **部分情况下CSS动画优于JS动画:**JS动画写法多种多样,在有很大优化空间的情况下JS的性能会更好一些,不同的动画库的性能也会不一样,因此二者的性能比较不是绝对的
  • **CSS中有一些高危属性:**比如box-shadow等,box-shadow在做动画的时候,CPU可能明显的发热,要慎用

2.23 常见的CSS预处理器

  • Less(Node.js)
  • Sass(Ruby 有Node的版本)
  • 其实还有别的预处理器,这两种更常见
  • **预处理器的作用:**可以帮助更好地组织CSS代码,提高代码的复用性,提升可维护性

2.24 预处理器的能力

  • 嵌套,反映层级和约束
  • 通过变量和计算,减少重复代码
  • Extend和Mixin代码片段能够复用大段代码
  • 循环,适用于复杂有规律的样式
  • import CSS文件模块化,更加集成,按需拆解CSS文件

2.25 预处理器的优缺点

  • 优点:提高代码复用率和可维护性
  • 缺点:需要引入编译过程,有学习成本

2.26 Bootstrap的优缺点

  • 优点:CSS代码结构合理,有现成的样式可以使用
  • 缺点:定制较为繁琐,体积相对较大

2.27 Bootstrap如何实现响应式布局

  • 原理:通过media query设置不同分辨率的class
  • 使用:为不同分辨率选择不同的网格class

2.28 如何基于Bootstrap定制自己的样式

  • 使用CSS同名类覆盖。这个方法非常简单,但是缺点是覆盖的可能不完全,没办法大面积的更改
  • 修改源码重新构建。这种方式非常何理,修改的很彻底,然而有一定的门槛
  • 引用scss源文件,使用minxin 的方法修改变量,形成自己的css文件

3 JavaScript

3.1 作用域、异步、闭包

for(var i=0; i<=3; i++){
  setTimeout(function(){
    console.log(i)
  }, 1000);
}

本题的答案是:3 3 3 3

这道题简化来看,先剥去循环的外壳:

setTimeout(function(){
	console.log(1);
}, 1000);
console.log(2);  //先打印2,1s后打印1

去掉循环之后,剩下的就是一个单纯的setTimeout 异步问题

setTimeout可以这样理解:该函数有两个参数,第一个参数是一个函数,第二个参数是时间值,调用该函数之后,实现把第一个参数,即函数参数放到事件队列中,等到主程序运行完再调用事件队列中的方法。

这就像给按钮绑定事件一样,你在onclick方法中写出来了一些功能,页面加载之后不会直接运行这个功能,而是需要触发事件,点击按钮后才会呈现。setTimeout也是这样,可以理解为只是绑定事件,等到主程序运行完之后,再去调用。

了解了这一点之后,我们再回到循环中看,循环的本质实际上就是将循环体内的部分重复执行,那本题就可以看作是这样的:

var i = 0;
setTimeout(function() {
	console.log(i);
}, 1000);
i++;

setTimeout(function() {
	console.log(i);
}, 1000);
i++;

setTimeout(function() {
	console.log(i);
}, 1000);
i++;

那根据上面讲到的异步问题,这几个i++;的语句是主程序里面的,先运行这一部分,等价于这样的写法:

var i = 0;
i++;
i++;
i++;
setTimeout(function() {
	console.log(i);
}, 1000);
setTimeout(function() {
	console.log(i);
}, 1000);
setTimeout(function() {
	console.log(i);
}, 1000);

因此输出的是 3 3 3.

那我们怎么解决这个问题呢?

方法一:使用let声明i,让循环体中变块级作用域

for(let i=0; i<=3; i++){

setTimeout(function(){ console.log(i) }, 1000); }

这里是将i的作用域从全局变量变成了块级变量,let将i重新绑定到循环体的每一次迭代中,确保上一次迭代结束的i被重新赋值。setTimeout里面的function()属于一个新的域,通过var定义的变量无法传入到这个函数的执行域中,而使用let声明的声明块级变量,这时候变量就能作用与这个块,有点儿类似类的属性。

方法二:使用立即执行函数

for(var i=0; i<=3; i++){

(function(){ var j=i; setTimeout(function(){ console.log(j) }, 1000); })(); }

或者这样:
```javascript
for (var i = 0; i <= 3; i++) {
 setTimeout((function(i) {
     return function() {
         console.log(i);
     };
 })(i), 0);  //改为立即执行的函数

}

不理解立即执行函数的,[看这里~](https://blog.csdn.net/csdn_yudong/article/details/77431106)