端面试题整理
已同步到掘金、CSDN
掘金地址: https://juejin.cn/post/7075332630417244173
CSDN 地址:https://blog.csdn.net/z1832729975/article/details/123431083
个人整理了很多网上常见的面试题,希望也能通过这来复习
内容有点多,可能 CSDN 上预览效果不好,想要 markdown 文档的可以私信我,推荐使用Typora
看
比较好的面试题
2021 年我的前端面试准备
2021 年前端面试必读文章【超三百篇文章/赠复习导图】
CSS、HTML
浏览器内核
IE: trident 内核
Firefox:gecko 内核
Safari: webkit 内核
Opera: 以前是 presto 内核,Opera 现已改用 GoogleChrome 的 Blink 内核
Chrome: Blink(基于 webkit,Google 与 Opera Software 共同开发)
你是怎么理解 HTML 语义化
HTML 语义化简单来说就是用正确的标签来做正确的事。
比如表示段落用 p 标签、表示标题用 h1-h6 标签、表示文章就用 article 等。
DOCTYPE 的作用
-
<!DOCTYPE>
声明位于文档中的最前面,处于<html>
标签之前。告知浏览器以何种模式来渲染文档。 -
严格模式的排版和 JS 运作模式是 以该浏览器支持的最高标准运行。
-
在混杂模式中,页面以宽松的向后兼容的方式显示。模拟老式浏览器的行为以防止站 点无法工作。
-
DOCTYPE 不存在或格式不正确会导致文档以混杂模式呈现。复制代码 你知道多少种 Doctype 文档类型? 该标签可声明三种 DTD 类型,分别表示严格版本、过渡版本以及基于框架的 HTML 文档。 HTML 4.01 规定了三种文档类型:Strict、Transitional 以及 Frameset。 XHTML 1.0 规定了三种 XML 文档类型:Strict、Transitional 以及 Frameset。 Standards (标准)模式(也就是严格呈现模式)用于呈现遵循最新标准的网页,而 Quirks (包容)模式(也就是松散呈现模式或者兼容模式)用于呈现为传统浏览器而设计的网页。
行内元素、块级元素、 空元素有那些?
- 行内元素 (不能设置宽高,设置宽高无效) a,span,i,em,strong,label
- 行内块元素:img, input
- 块元素: div, p, h1-h6, ul,li,ol,dl,table…
- 知名的空元素 br, hr,img, input,link,meta
可以通过 display 修改 inline-block
, block
, inline
注意
只有文字才能组成段落,因此 p
标签里面不能放块级元素,特别是 p
标签不能放 div
。同理还有这些标签h1,h2,h3,h4,h5,h6,dt
,他们都是文字类块级标签,里面不能放其他块级元素。
meta viewport 是做什么用的,怎么写
使用目的
告诉浏览器,用户在移动端时如何缩放页面
<meta
name="viewport"
content="width=device-width,
initial-scale=1,
maximum-scale-1, minimum-scale=1"
/>
with=device-width
将布局视窗(layout viewport)的宽度设置为设备屏幕分辨率的宽度
initial-scale=1
页面初始缩放比例为屏幕分辨率的宽度
maximum-scale=1
指定用户能够放大的最大比例
minimum-scale=1
指定用户能够缩小的最大比例
label 标签的作用
label 标签来定义表单控制间的关系,当用户选择该标签时,浏览器会自动将焦点转到和标签相关的表单控件上。
<label for="Name">Number:</label>
<input type="text" name="Name" id="Name" />
<label
>Date:
<input type="text" name="B" />
</label>
canvas 在标签上设置宽高 和在 style 中设置宽高有什么 区别
canvas 标签的 width 和 height 是画布实际宽度和高度,绘制的图形都是在这个上面。
而 style 的 width 和 height 是 canvas 在浏览器中被渲染的高度和宽度。
如果 canvas 的 width 和 height 没指定或值不正确,就被设置成默认值 。
html5 新特性
- 语义化标签, header, footer, nav, aside,article,section
- 增强型表单
- 视频 video 和音频 audio
- Canvas 绘图
- SVG绘图
- 地理定位
- 拖放 API
- WebWorker
- WebStorage( 本地离线存储 localStorage、sessionStorage )
- WebSocket
css3 新特性
1、圆角效果;2、图形化边界;3、块阴影与文字阴影;4、使用 RGBA 实现透明效果;5、渐变效果;6、使用“@Font-Face”实现定制字体;7、多背景图;8、文字或图像的变形处理;9、多栏布局;10、媒体查询等。
1、颜色:新增RGBA、HSLA模式
2、文字阴影:(text-shadow)
3、边框:圆角(border-radius)边框阴影:box-shadow
4、盒子模型:box-sizing
5、背景:background-size,background-origin background-clip(削弱)
6、渐变:linear-gradient(线性渐变):
eg: background-image: linear-gradient(100deg, #237b9f, #f2febd);
radial-gradient (径向渐变)
7、过渡:transition可实现动画
8、自定义动画: animate@keyfrom
9、媒体查询:多栏布局@media screen and (width:800px)
10、border-image
11、2D转换:transform:translate(x,y) rotate(x,y)旋转 skew(x,y)倾斜 scale(x,y)缩放
12、3D转换
13、字体图标:Font-Face
14、弹性布局:flex
css 选择器
id 选择器( #myid)
类选择器(.myclassname)
标签选择器(div, h1, p)相邻选择器(h1 + p)
子选择器(ul > li)后代选择器(li a)
属性选择器(a[rel = “external”])
伪类选择器(a: hover, li:nth-child)
通配符选择器( * )
!Important > 行内式 > id > 类/伪类/属性 > 标签选择器 > 全局
(对应权重:无穷大∞ > 1000> 100 > 10 > 1 > 0)
盒模型
一个盒子,会有 content,padding,border,margin 四部分,
标准的盒模型的宽高指的是 content 部分
ie 的盒模型的宽高包括了 content+padding+border
我们可以通过 box-sizing 修改盒模型,box-sizing border-box
content-box
margin 合并
在垂直方向上的两个盒子,他们的 margin 会发生合并(会取最大的值),比如上边盒子设置margin-bottom:20px
,下边盒子设置margin-top:30px;
,那么两个盒子间的间距只有30px
,不会是50px
解决 margin 合并,我们可以给其中一个盒子套上一个父盒子,给父盒子设置 BFC
margin 塌陷
效果: 一个父盒子中有一个子盒子,我们给子盒子设置margin-top:xxpx
结果发现会带着父盒子一起移动(就效果和父盒子设置margin-top:xxpx
的效果一样)
解决: 1、给父盒子设置 border,例如设置border:1px solid red;
2、给父盒子设置 BFC
BFC
块级格式化上下文 (block format context)
BFC 的布局规则 *
- 内部的 Box 会在垂直方向,一个接一个地放置。
- Box 垂直方向的距离由 margin 决定。属于同一个 BFC 的两个相邻 Box 的 margin 会发生重叠。
- 每个盒子(块盒与行盒)的 margin box 的左边,与包含块 border box 的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
- BFC 的区域不会与 float box 重叠。
- BFC 就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
- 计算 BFC 的高度时,浮动元素也参与计算。
触发 BFC 的条件 *
- 根元素 html
- float 的值不是 none。
- position 的值 absoute、fixed
- display 的值是 inline-block、table-cell、flex、table-caption 或者 inline-flex
- overflow 的值不是 visible
解决什么问题
-
可以用来解决两栏布局
BFC 的区域不会与 float box 重叠
.left { float: flet; } .right { overflow: hidden; }
-
解决 margin 塌陷和 margin 合并问题
-
解决浮动元素无法撑起父元素
flex
设为 Flex 布局以后,子元素的 float、clear 和 vertical-align 属性将失效
什么是 rem、px、em 区别
rem 是一个相对单位,rem 的是相对于 html 元素的字体大小,没有继承性
em 是一个相对单位,是相对于父元素字体大小有继承性
px 是一个“绝对单位”,就是 css 中定义的像素,利用 px 设置字体大小及元素的宽高等,比较稳定和精确。
响应式布局
响应式布局有哪些实现方式?什么是响应式设计?响应式设计的基本原理是什么?
1.百分比布局,但是无法对字体,边框等比例缩放
2.弹性盒子布局 display:flex
3.rem 布局,1rem=html 的 font-size 值的大小
- css3 媒体查询 @media screen and(max-width: 750px){}
5.vw+vh
6.使用一些框架(bootstrap,vant)
什么是响应式设计:响应式网站设计是一个网站能够兼容多个终端,智能地根据不同设备环境进行相对应的布局
响应式设计的基本原理:基本原理是通过媒体查询检测不同的设备屏幕尺寸设置不同的 css 样式 页面头部必须有 meta 声明的
布局
- 两栏布局,左边定宽,右边自适应
- 三栏布局、圣杯布局、双飞翼布局
水平垂直居中
方法一:给父元素设置成弹性盒子,子元素横向居中,纵向居中
方法二:父相子绝后,子部分向上移动本身宽度和高度的一半,也可以用 transfrom:translate(-50%,-50%)(最常用方法)
方法三:父相子绝,子元素所有定位为 0,margin 设置 auto 自适应
iframe 有哪些缺点?
iframe 是一种框架,也是一种很常见的网页嵌入方
iframe 的优点:
- iframe 能够原封不动的把嵌入的网页展现出来。
- 如果有多个网页引用 iframe,那么你只需要修改 iframe 的内容,就可以实现调用的每一个页面内容的更改,方便快捷。
- 网页如果为了统一风格,头部和版本都是一样的,就可以写成一个页面,用 iframe 来嵌套,可以增加代码的可重用。
- 如果遇到加载缓慢的第三方内容如图标和广告,这些问题可以由 iframe 来解决。
iframe 的缺点:
- 会产生很多页面,不容易管理。
- iframe 框架结构有时会让人感到迷惑,如果框架个数多的话,可能会出现上下、左右滚动条,会分散访问者的注意力,用户体验度差。
- 代码复杂,无法被一些搜索引擎索引到,这一点很关键,现在的搜索引擎爬虫还不能很好的处理 iframe 中的内容,所以使用 iframe 会不利于搜索引擎优化。
- 很多的移动设备(PDA 手机)无法完全显示框架,设备兼容性差。
- iframe 框架页面会增加服务器的 http 请求,对于大型网站是不可取的。现在基本上都是用 Ajax 来代替 iframe,所以 iframe 已经渐渐的退出了前端开发。
link @import 导入 css
link 是 XHTML 标签,除了加载 CSS 外,还可以定义 RSS 等其他事务;
@import 属于 CSS 范畴, 只能加载 CSS。
link 引用 CSS 时,在页面载入时同时加载;@import 需要页面网页完全载入以后加载。link
无兼容问题;@import 是在 CSS2.1 提出的,低版本的浏览器不支持。
link 支持使用 Javascript 控制 DOM 去改变样式;而@import 不支持。
DOM 事件机制/模型
DOM0 级模型、IE 事件模型、DOM2 级事件模型
就比如用户触发一个点击事件,有一个触发的过程
事件捕获-阶段(从上大小,从外到内)—>处于目标事件-阶段---->事件冒泡-阶段(从下到上,从内到外)
window.addEventListener(
"click",
function (event) {
event = event || window.event /*ie*/;
const target = event.target || event.srcElement; /*ie*/ // 拿到事件目标
// 阻止冒泡
// event.stopPropagation()
// event.cancelBubble=true; // ie
// 阻止默认事件
// event.preventDefault();
// event.returnValue=false; // ie
},
/* 是否使用捕获,默认是fasle, */ fasle
);
事件委托
简介:事件委托指的是,不在事件的发生地(直接 dom)上设置监听函数,而是
在其父元素上设置监听函数,通过事件冒泡,父元素可以监听到子元素上事件的
触发,通过判断事件发生元素 DOM 的类型,来做出不同的响应。
举例:最经典的就是 ul 和 li 标签的事件监听,比如我们在添加事件时候,采用
事件委托机制,不会在 li 标签上直接添加,而是在 ul 父元素上添加。
好处:比较合适动态元素的绑定,新添加的子元素也会有监听函数,也可以有事
件触发机制
如果需要手动写动画,你认为最小时间间隔是多久
多数显示器默认频率是 60Hz,即 1 秒刷新 60 次,所以理论上最小间隔为
1/60*1000ms = 16.7ms
::before和:after中双冒号和单冒号有什么区别
单冒号(:)用于 CSS3 伪类,双冒号(::)用于 CSS3 伪元素。 ::before 就是以一个子元素的存在,定义在元素主体内容之前的一个伪元素。并不存在于 dom 之中,只存在在页面之中。 :before 和 :after 这两个伪元素,是在 CSS2.1 里新出现的。起初,伪元素的前缀使用的是单 冒号语法,但随着 Web 的进化,在 CSS3 的规范里,伪元素的语法被修改成使用双冒号,成 为::before ::after
CSS sprites 精灵图
CSS Sprites 其实就是把网页中一些背景图片整合到一张图片文件中,再利用 CSS 的 “background-image”,“ background-repeat ”,“ background-position”
的 组 合 进 行 背 景 定 位 , background-position 可以用数字能精确的定位出背景图片的位置。这样可以减少很多图片请 求的开销,因为请求耗时比较长;请求虽然可以并发,但是也有限制,一般浏览器都是 6 个
重排和重绘
重绘(repaint 或 redraw):当盒子的位置、大小以及其他属性,例如颜色、字 体大小等都确定下来之后,浏览器便把这些原色都按照各自的特性绘制一遍,将 内容呈现在页面上。重绘是指一个元素外观的改变所触发的浏览器行为,浏览器 会根据元素的新属性重新绘制,使元素呈现新的外观。
触发重绘的条件:改变元素外观属性。如:color,background-color 等。 注意:table 及其内部元素可能需要多次计算才能确定好其在渲染树中节点的属性值,比同等元素要多花两倍时间,这就是我们尽量避免使用 table 布局页面的 原因之一。
重排(重构/回流/reflow):当渲染树中的一部分(或全部)因为元素的规模尺寸, 布局,隐藏等改变而需要重新构建, 这就称为回流(reflow)。每个页面至少需要 一次回流,就是在页面第一次加载的时候。
重绘和重排的关系:在回流的时候,浏览器会使渲染树中受到影响的部分失效, 并重新构造这部分渲染树,完成回流后,浏览器会重新绘制受影响的部分到屏幕 中,该过程称为重绘。所以,重排必定会引发重绘,但重绘不一定会引发重排。
JavaScript
js 数据类型
8 中, ES6
出的 Symbol BigInt
Number String Boolean undefined null Object Symbol BigInt
js 的基本数据类型和复杂数据类型的区别(在堆和栈中,赋值时的不同,一个拷贝值一个拷贝地址)
基本类型和引用类型在内存上存储的区别
null 与 undefined 的异同
相同点:
- Undefined 和 Null 都是基本数据类型,这两个基本数据类型分别都只有一个值,就是 undefined 和 null
不同点:
-
null 转换成数字是 0, undefined 转换数字是
NaN
-
undefined 代表的含义是未定义, null 代表的含义是空对象。
-
typeof null 返回’object’,typeof undefined 返回’undefined’
-
null == undefined; // true null === undefined; // false
-
其实 null 不是对象,虽然 typeof null 会输出 object,但是这只是 JS 存在的一个悠久 Bug。在 JS 的最初版本中使用的是 32 位系统,为了性能考虑使用低位存储变量的类型信息,000 开头代表是对象,然而 null 表示为全零,所以将它错误的判断为 object 。虽然现在的内部类型判断代码已经改变了,但是对于这个 Bug 却是一直流传下来。
说说 JavaScript 中判断数据类型的几种方法
typeof
typeof
一般用来判断基本数据类型,除了判断 null 会输出"object",其它都是正确的typeof
判断引用数据类型时,除了判断函数会输出"function",其它都是输出"object"
instanceof
Instanceof 可以准确的判断引用数据类型,它的原理是检测构造函数的
prototype
属性是否在某个实例对象的原型链上, 不能判断基本数据类型
// instanceof 的实现
function instanceofOper(left, right) {
const prototype = right.prototype;
while (left) {
if ((left = left.__proto__) === prototype) {
return true;
}
}
return false;
}
// let obj = {}
// Object.getPrototypeOf(obj) === obj.__proto__ ==> true
// 实现 instanceof 2
function myInstanceof(left, right) {
// 这里先用typeof来判断基础数据类型,如果是,直接返回false
if (typeof left !== "object" || left === null) return false;
// getProtypeOf是Object对象自带的API,能够拿到参数的原型对象
let proto = Object.getPrototypeOf(left);
while (true) {
if (proto === null) return false;
if (proto === right.prototype) return true; //找到相同原型对象,返回true
proto = Object.getPrototypeof(proto);
}
}
Object.prototype.toString.call() 返回 [object Xxxx]
都能判断
深拷贝和浅拷贝
let obj = { b: "xxx" };
let arr = [{ a: "ss" }, obj, 333];
// 赋值
let arr2 = arr;
// 浅拷贝-只拷贝了一层,深层次的引用还是存在
// Object.assign(), ...扩展运算符,slice等
let arr2 = arr.slice();
let arr2 = [...arr];
obj.b = "222"; // arr2[1].b => 222
// arr[2] = 4444 ==> arr2[2] ===> 333
// 深拷贝
// 1. 最简单的,JSON.stringify,但这个有问题,看下面有说明
let arr2 = JSON.parse(JSON.stringify(arr));
// 2. 自己封装,要递归处理
实现深拷贝-简单版
export function deepClone(obj, map = new Map()) {
if (!obj && typeof obj !== "object") return obj;
if (obj instanceof Date) return new Date(obj);
if (obj instanceof RegExp) return new RegExp(obj.source, obj.flags);
if (map.get(obj)) {
// 如果有循环引用、就返回这个对象
return map.get(obj);
}
const cloneObj = obj.constructor(); // 数组的就是[],对象就是{}
map.set(obj, cloneObj); // 缓存对象,用于循环引用的情况
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
cloneObj[key] = deepClone(obj[key], map);
}
}
return cloneObj;
}
JSON.stringify
问题
-
如果有循环引用就报错
-
Symbol
、function
、undefined
会丢失 -
布尔值
、数字
、字符串
的包装对象会转换成原始值 -
NaN
、Infinity
变成null
-
Date
类型的日期会变成字符串 -
RegExp
、Error
被转换成了空对象{}
模块化
-
commonjs
// 由nodejs实现 const fs = require("fs"); module.exports = {};
-
ESM
// 由es6实现 import $ from "jquery"; export default $;
-
AMD(异步加载模块)
// 由RequireJS实现 define(["juqery", "vue"], function ($, Vue) { // 依赖必须一开始就写好 $("#app"); new Vue({}); });
-
CMD
// 由SeaJS 实现 define(function (require, exports, module) { var a = require("./a"); a.doSomething(); // .... var b = require("./b"); // 依赖可以就近书写 b.doSomething(); // ... });