HTML
如何理解HTML语义化
- 增加代码的可读性
- 让搜索引擎更加容易读懂,有助于爬虫抓取更多有效的信息, 爬虫依赖于标签来确定上下文和关键字的权重(SEO)
- 在没有CSS样式下,页面也能更好的呈现代码、内容结构
script 标签中 defer 和 async 的区别?
script: 会阻碍HTML解析,只有下载好了并执行完脚本之后才会继续解析HTMLdefer: 完全不会阻碍HTML解析,会异步下载脚本,当HTML解析完成之后,按照顺序执行脚本async: 异步下载脚本,立马执行脚本,此时会阻碍HTML解析
#### 从浏览器地址栏输入 url 到请求返回发生了什么
解析URL: 输入一个URL之后,解析出协议、主机、端口、路径等细心,并构造一个http请求缓存判断:判断是否有缓存(强缓存和协商缓存),有则用,无则向服务端发起请求DNS解析:获取IP地址。向本地的DNS服务器查找有无缓存,有则用,无则先向根域名服务器发起请求-->获得负责的顶级域名服务器的地址后 -->向顶级域名服务器请求->获得负责的权威域名服务器的地址后,再向权威域名服务器发起请求->DNS获得ip,返回给用户->用户向本地 DNS 服务器发起请求属于递归请求,本地 DNS 服务器向各级域名服务器发起请求属于迭代请求。获取MAC地址TCP三次握手:HTTPS握手:如果使用的是 HTTPS 协议,在通信前还存在 TLS 的一个四次握手的过程返回数据:服务端会返回一个html文件作为响应,浏览器接受之后,开始对其解析,开始页面渲染页面渲染:根据HTML构建dom树,css构建cssom树,遇到script标签,判断defer或者是async属性,否则会造成页面渲染阻塞。当dom树以及cssom树构建完成之后,会根据二者来构建渲染树,再等渲染树构建完成,会根据渲染树来进行布局,布局完成之后,最后使用浏览器的UI接口对页面进行绘制,最后展示出页面。TCP四次握手:
CSS
盒模型介绍
类型:标准盒模型、IE盒模型
结构:content + padding + border + margin
盒子内容宽度以及高度计算:
标准盒模型:contentIE盒模型:content + padding + border
css 选择器和优先级
- 一般情况下:
!important > style > id > class- 特殊的优先级算法规则:(a,b,c,d)a代表:1. 如果存在内联样式,那么
a = 1, 否则a = 0;1.b的值等于ID选择器出现的次数;1.c的值等于类选择器和属性选择器和伪类出现的总次数;1.d的值等于标签选择器和伪元素出现的总次数 。- 比较规则:比较规则是: 从左往右依次进行比较 ,较大者胜出,如果相等,则继续往右移动一位进行比较 。如果4位全部相等,则后面的会覆盖前面的。例如(0, 1, 1, 0)大于 (0, 0, 2, 0)
- tips:内联样式优先级很高;代码慎用!important
重排以及重绘
简单地总结下两者的概念:
-
重排:无论通过什么方式影响了元素的几何信息(元素在视口内的位置和尺寸大小),浏览器需要重新计算元素在视口内的几何属性,这个过程叫做重排。(布局改变重新绘制,必定出发重绘)
-
重绘:通过构造渲染树和重排(回流)阶段,我们知道了哪些节点是可见的,以及可见节点的样式和具体的几何信息(元素在视口内的位置和尺寸大小),接下来就可以将渲染树的每个节点都转换为屏幕上的实际像素,这个阶段就叫做重绘。(元素几何信息未改变,而只是样式改变,颜色等等,不一定发生重排。)
-
如何减少重排和重绘
- 最小化重绘和重排,样式集中更改
- 减少dom操作
- 脱离文档流
absolute fixed
BFC
- 概念
- block formatting context 块级格式化上下文
- 形成自己的一个独立区域
- 内部元素渲染不会影响到外界
- 特性
1块级元素会在垂直方向一个接一个的排列,和文档流的排列方式一致。2在 BFC 中上下相邻的两个容器的margin会重叠,创建新的 BFC 可以避免外边距重叠。3计算 BFC 的高度时,需要计算浮动元素的高度。4BFC 区域不会与浮动的容器发生重叠。5BFC 是独立的容器,容器内部元素不会影响外部元素。6每个元素的左margin值和容器的左border相接触。
- 常见问题解决方式
- 利用
4和6,我们可以实现三栏(或两栏)自适应布局。- 利用
2,我们可以避免margin重叠问题。- 利用
3,我们可以避免高度塌陷。
- 创建常见条件(满足其一即可)
- 浮动属性 float 不是none
- 绝对定位属性 position是absolute或者是fixed
- 块级元素overflow属性 不是visible
- flex元素
- inline-block元素
flex 布局
概念 弹性布局(Flexible Box)
flex属性设置
.box{
display: flex;
}
.box{
display: inline-flex;
}
flex属性
- flex-direction:
row | row-reverse | column | column-reverse- flex-wrap:
nowrap | wrap | wrap-reverse- justify-content:
flex-start | flex-end | center | space-between | space-around- align-items:
flex-start | flex-end | center | baseline | stretch
实现两栏布局(左侧固定 + 右侧自适应布局)
现在有以下 DOM 结构:
<div class="outer">
<div class="left">左侧</div>
<div class="right">右侧</div>
</div>
复制代码
- 利用浮动,左边元素宽度固定 ,设置向左浮动。将右边元素的
margin-left设为固定宽度 。注意,因为右边元素的width默认为auto,所以会自动撑满父元素。
.outer {
height: 100px;
}
.left {
float: left;
width: 200px;
height: 100%;
background: lightcoral;
}
.right {
margin-left: 200px;
height: 100%;
background: lightseagreen;
}
复制代码
- 同样利用浮动,左边元素宽度固定 ,设置向左浮动。右侧元素设置
overflow: hidden;这样右边就触发了BFC,BFC的区域不会与浮动元素发生重叠,所以两侧就不会发生重叠。
.outer {
height: 100px;
}
.left {
float: left;
width: 200px;
height: 100%;
background: lightcoral;
}
.right {
overflow: auto;
height: 100%;
background: lightseagreen;
}
复制代码
- 利用
flex布局,左边元素固定宽度,右边的元素设置flex: 1。
.outer {
display: flex;
height: 100px;
}
.left {
width: 200px;
height: 100%;
background: lightcoral;
}
.right {
flex: 1;
height: 100%;
background: lightseagreen;
}
复制代码
- 利用绝对定位,父级元素设为相对定位。左边元素
absolute定位,宽度固定。右边元素的margin-left的值设为左边元素的宽度值。
.outer {
position: relative;
height: 100px;
}
.left {
position: absolute;
width: 200px;
height: 100%;
background: lightcoral;
}
.right {
margin-left: 200px;
height: 100%;
background: lightseagreen;
}
复制代码
- 利用绝对定位,父级元素设为相对定位。左边元素宽度固定,右边元素
absolute定位,left为宽度大小,其余方向定位为0。
.outer {
position: relative;
height: 100px;
}
.left {
width: 200px;
height: 100%;
background: lightcoral;
}
.right {
position: absolute;
left: 200px;
top: 0;
right: 0;
bottom: 0;
height: 100%;
background: lightseagreen;
}
复制代码
实现圣杯布局和双飞翼布局(经典三分栏布局)
圣杯布局和双飞翼布局的目的:
- 三栏布局,中间一栏最先加载和渲染(内容最重要,这就是为什么还需要了解这种布局的原因)。
- 两侧内容固定,中间内容随着宽度自适应。
- 一般用于 PC 网页。
圣杯布局和双飞翼布局的技术总结:
- 使用
float布局。 - 两侧使用
margin负值,以便和中间内容横向重叠。 - 防止中间内容被两侧覆盖,圣杯布局用
padding,双飞翼布局用margin。
圣杯布局: HTML 结构:
<div id="container" class="clearfix">
<p class="center">我是中间</p>
<p class="left">我是左边</p>
<p class="right">我是右边</p>
</div>
复制代码
CSS 样式:
#container {
padding-left: 200px;
padding-right: 150px;
overflow: auto;
}
#container p {
float: left;
}
.center {
width: 100%;
background-color: lightcoral;
}
.left {
width: 200px;
position: relative;
left: -200px;
margin-left: -100%;
background-color: lightcyan;
}
.right {
width: 150px;
margin-right: -150px;
background-color: lightgreen;
}
.clearfix:after {
content: "";
display: table;
clear: both;
}
复制代码
双飞翼布局: HTML 结构:
<div id="main" class="float">
<div id="main-wrap">main</div>
</div>
<div id="left" class="float">left</div>
<div id="right" class="float">right</div>
复制代码
CSS 样式:
.float {
float: left;
}
#main {
width: 100%;
height: 200px;
background-color: lightpink;
}
#main-wrap {
margin: 0 190px 0 190px;
}
#left {
width: 190px;
height: 200px;
background-color: lightsalmon;
margin-left: -100%;
}
#right {
width: 190px;
height: 200px;
background-color: lightskyblue;
margin-left: -190px;
}
复制代码
tips:上述代码中 margin-left: -100% 相对的是父元素的 content 宽度,即不包含 paddig 、 border 的宽度。
其实以上问题需要掌握 margin 负值问题 即可很好理解。
水平垂直居中多种实现方式
- 利用绝对定位,设置
left: 50%和top: 50%现将子元素左上角移到父元素中心位置,然后再通过translate来调整子元素的中心点到父元素的中心。该方法可以不定宽高。
.father {
position: relative;
}
.son {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
复制代码
- 利用绝对定位,子元素所有方向都为
0,将margin设置为auto,由于宽高固定,对应方向实现平分,该方法必须盒子有宽高。
.father {
position: relative;
}
.son {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0px;
margin: auto;
height: 100px;
width: 100px;
}
复制代码
- 利用绝对定位,设置
left: 50%和top: 50%现将子元素左上角移到父元素中心位置,然后再通过margin-left和margin-top以子元素自己的一半宽高进行负值赋值。该方法必须定宽高。
.father {
position: relative;
}
.son {
position: absolute;
left: 50%;
top: 50%;
width: 200px;
height: 200px;
margin-left: -100px;
margin-top: -100px;
}
复制代码
- 利用
flex,最经典最方便的一种了,不用解释,定不定宽高无所谓的。
.father {
display: flex;
justify-content: center;
align-items: center;
}
复制代码
JS
数据类型
基本数据类型介绍
Undefined、Null、Boolean、Number、String、Object、Symbol、BigInt- es6新增
BigInt、Symbol
引用类型以及值类型
- 值类型(
Undefined、Null、Number、String、Boolean、Symbol)是直接存储在**栈(stack)**中的简单数据段,占据空间小、大小固定,属于被频繁使用数据,所以放入栈中存储;- 引用类型(Object、Arrar、fn、Date、RexExp)存储在**堆(heap)**中的对象,占据空间大、大小不固定。如果存储在栈中,将会影响程序运行的性能;
数据类型判断
- typeof:能判断所有值类型,函数。不可对 null、对象、数组进行精确判断,因为都返回
object- instanceof:判断对象类型,不能判断基本数据类型,其内部运行机制是判断原型链中是否能找到该类型的原型(顺着__proto__这条链路找下去);数组不能准确判断:[] instanceof Array 和 [] instanceof Object都为true
- Object.prototype.toString.call() :所有原始数据类型都是能判断的,还有 Error 对象,Date 对象等
判断变量为数组:
在面试中有一个经常被问的问题就是:如何判断变量是否为数组?
Array.isArray(arr); // true
arr.__proto__ === Array.prototype; // true
arr instanceof Array; // true
Object.prototype.toString.call(arr); // "[object Array]"
深浅拷贝
- 浅拷贝是创建一个新对象,新对象属性是原对象属性的精确拷贝。如果是值类型,则拷贝基本类型的值,如果是引用类型,则是拷贝的是内存地址 从堆内存中开辟一个新的区域存放原对象的拷贝对象,且新对象的更新不会影响到旧对象
/**
* @description:深拷贝
* @param {Object} object //当前拷贝对象属性
* @param {Object} map // 判断当前属性是否存在映射,避免属性指向本身xx.xx = xx
* @return {Object} //完成深拷贝的属性(对象)
*/
const deepClone = (object = {}, map = new Map()) => {
if (typeof object !== "object") {
return object;
}
if (map.get(object)) {
return map.get(object);
}
let res = {};
map.set(object, {});
if (
Array.isArray(object) ||
Object.prototype.toString.call(object) === "[object Array]"
) {
res = [];
}
for (let k in object) {
if (object.hasOwnProperty(k)) {
res[k] = deepClone(object[k], map);
}
}
return res;
};
0.1+0.2 ! == 0.3
原因总结
js在做数字运算的时候,0.1和0.2都会转换成二进制无限不循环,但是 js 采用的 IEEE 754 二进制浮点运算,最大可以存储 53 位有效数字,于是大于 53 位后面的会全部截掉,将导致精度丢失
解决办法
- 转为整数运算
- 字符串相加减
- ...
原型以及原型链
可以说这部分每家面试官都会问了。。首先理解的话,其实一张图即可
总结:
- 原型:每一个 JavaScript 对象(null 除外)在创建的时候就会与之关联另一个对象,这个对象就是我们所说的原型,每一个对象都会从原型"继承"属性,其实就是
prototype对象。 - 原型链:由相互关联的原型组成的链状结构就是原型链。
先说出总结的话,再举例子说明如何顺着原型链找到某个属性。
作用域与作用域链
-
作用域:规定了如何查找变量,也就是确定当前执行代码对变量的访问权限。换句话说,作用域决定了代码区块中变量和其他资源的可见性。(全局作用域、函数作用域、块级作用域)
-
作用域链:从当前作用域开始一层层往上找某个变量,如果找到全局作用域还没找到,就放弃寻找 。这种层级关系就是作用域链。(由多个执行上下文的变量对象构成的链表就叫做作用域链,学习下面的内容之后再考虑这句话)
4、 执行上下文
指当前执行环境中的变量、函数声明,参数(arguments),作用域链,this等信息。 分为全局执行上下文、函数执行上下文,其区别在于全局执行上下文只有一个,函数执行上下文在每次调用函数时候会创建一个新的函数执行上下文。
总结:当 JavaScript 代码执行一段可执行代码时,会创建对应的执行上下文。对于每个执行上下文,都有三个重要属性:
- 变量对象(Variable object,VO);
- 作用域链(Scope chain);
- this。(指函数运行环境,
boo.fn()中fn的this指向boo,而let obj =boo.fn,obj()的this指向obj所处的运行环境 中:JavaScript 的 this 原理)