这篇文章记录,前端的各种专业名次,基础知识,为个人笔记,适合刚开始学习前端,基础知识尚不完善的小伙伴阅读,文章内容都是很常见的前端基础,同时会不断完善
BFC
BFC是页面上的一个隔离的独立容器,里面的元素不会影响到外面的元素,同样外面的元素也不会影响到里面的元素。
触发bfc的条件
- 根元素或其它包含它的元素;
- 浮动 (元素的
float不为none); - 绝对定位元素 (元素的
position为absolute或fixed); - 行内块
inline-blocks(元素的display: inline-block); - 表格单元格(元素的
display: table-cell,HTML表格单元格默认属性); overflow的值不为visible的元素;- 弹性盒 flex boxes (元素的
display: flex或inline-flex);
但其中,最常见的就是overflow:hidden、float:left/right、position:absolute。也就是说,每次看到这些属性的时候,就代表了该元素以及创建了一个BFC了。
BFC的效果
-
内部的盒会在垂直方向一个接一个排列(可以看作BFC中有一个的常规流);
-
处于同一个BFC中的元素相互影响,可能会发生margin collapse;
-
每个元素的margin box的左边,与容器块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此;
-
BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素,反之亦然;
-
计算BFC的高度时,考虑BFC所包含的所有元素,连浮动元素也参与计算;
-
浮动盒区域不叠加到BFC上;
HTML语义化
html语义化的意思就是给HTML的标签赋予意义,例如,
标签表示这是一个纯文字段落,标签表示标题
语义化的标签有利于后期代码的维护
盒模型
盒模型是页面上一块包含
-
margin 外边距
-
padding 内边距
-
border 边框
-
content 内容区
的一块矩形区域
其中盒模型分为IE盒模型和标准盒模型,也就是w3c标准盒模型,IE盒模型的width和height包括padding和border,content,而w3c盒模型的width和height就只是content
null和undefined的区别
undefined是定义了但是没有赋值
例如
let a
console.log(a)
//undefined
null
em和rem的区别
em和rem都是一个相对单位
rem相对于根元素设定的font-size大小
em相对于使用em的元素的font-size的大小
解构/扩展运算符(...)
取出对象中所有可遍历属性,拷贝到当前对象中
let obj1 = {a:1 b:{c:1}}
let obj2 = {...obj1}
obj1==obj2
闭包
在es5中只有全局作用域和函数作用域,而且由于JavaScript的链式作用域结构,内部函数可以访问外部函数的作用域,但是外部函数 不可以访问内部函数的作用域。所以想访问内部函数的变量的时候,就需要闭包
闭包是指有权访问另一个函数作用域中变量的函数,常见的创建闭包的方式就是函数嵌套,就是在一个函数内部再创建一个新的函数,通过新函数访问原函数中的变量,利用闭包可以突破作用域链,闭包会保存函数作用域在内存中,不会被js的垃圾回收机制回收,如果大量使用闭包,有可能会导致内存泄漏!
js的垃圾回收机制
js的垃圾回收机制主要是回收局部变量,当函数执行完成之后,也就是生命周期结束之后,这个函数所声明的局部变量就会被回收,所占的内存就会被释放
垃圾回收机制分为两种
-
引用计数
记下被引用的次数,当引用次数为0时,被回收,缺点:当循环引用时无法被回收,需要手动释放
function func4 () { const c = {} // 引用类型变量 c的引用计数为 0 let d = c // c 被 d 引用 c的引用计数为 1 let e = c // c 被 e 引用 c的引用计数为 2 d = {} // d 不再引用c c的引用计数减为 1 e = null // e 不再引用 c c的引用计数减为 0 将被回收 } -
标记清除
当变量进入执行环境时,将变量标记为进入状态,当变量离开执行环境时,标记为离开状态
js垃圾回收机制会将离开状态的变量进行释放
promise(ES6)
promise是一个异步解决方案,解决es5中存在的回调地狱 ”callback hell“
promise有三个状态
- pending, 异步任务正在执行
- resolved(有时也叫fulfilled),异步任务执行成功
- rejected,异步任务执行失败
只有当promise状态变为 resolved或者rejected之后,.then中的方法才会执行
例如以下场景
我去面试
- 首先向公司投递简历,此时promise处于pending状态,.then()中等待返回状态,当成功通过筛选之后(返回resolved)进入下一步操作,没有通过筛选(返回rejected)处理错误/异常
- 开始一轮面试,进去下一轮pending状态,等待返回面试状态,.then()中等待返回状态,通过面试(返回resolved),进去下一步操作,没通过返回(rejected)处理错误/异常
- 拿到一轮面试成功通过状态,开始二轮面试,进去下一轮pending状态,等待返回面试状态,.then()中等待返回状态,通过面试(返回resolved),进入下一步操作,没通过返回(rejected)处理错误/异常
- 拿到二轮面试成功状态,通过面试,进入pending状态,等待返回offer,.then()中等待返回状态,成功收到offer(返回resolved),准备入职,没通过返回(rejected)处理错误/异常
async/await(ES7)
让写异步代码和写同步代码一样轻松
var let const的区别
-
var会变量提升,
-
let和const不会变量提升,
-
let和const创建块作用域,创建的变量只在创建的代码块中生效
-
let和const声明的全局变量不会挂在window对象下
-
const声明的常量,声明后必须马上赋值,赋值之后简单数据类型不能修改,复杂数据类型指针指向的地址不能修改
-
let和const有暂时性死区,因为不会变量提升,所以存在暂时性死区
暂时性死区:
只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量
暂时性死区和不能变量提升的意义在于:
为了减少运行时错误,防止在变量声明前就使用这个变量,从而导致意料之外的行为。
this
this是函数运行时指针, 指向对象由运行方式决定
- 作为对象的方法调用 this指向对象本身
- 作为普通函数调用 this指向全局, 严格模式下undefined
- 构造器调用,函数作为构造函数调用时, this指向实例化(new)后的对象
- 箭头函数没有自己的this值,箭头函数中所使用的this来自于函数作用域链
- call, apply, bind 手动指定this调用
*http&https
http:
http是无状态,无连接的连接协议,是一种 请求-响应 式的连接
无状态是指:http不会对客户端有状态储存,服务器并不知道是谁向自己发送请求
无连接是指:客户端发送连接,服务器响应之后即关闭连接,再次发起请求则再次建立连接,同一客户端短时间连续发请求,服务器并不知道有没有响应过这个客户端;
明文传输,无法验证数据完整性,由于无状态,不会验证通信方是谁,可能被中间人攻击
https:http + ssl
https采用加密传输,中间者无法直接获取明文
https会验证发送方身份,避免中间者攻击
https会验证数据完整性,避免数据别中间者修改
首先 建立安全的链接,通讯双方都必须使用密文,使用密文就必须要解密,此时,采用非对称解密的方式,使用一对秘钥,一个公开(公钥)一个保密(私钥),其中,一个加密一个解密,这样传输的密文只有拥有私钥的一样可以解密,从而达到建立安全连接的目的,考虑此时如果有一个中间人,在通讯中间伪装成双方,那么他就可以获取通讯信息,那么此时就引出了一个新的问题,如果确定公钥的归属?也就是如何安全的分发公钥?采用hash算法对数据完整性进行保护,hash算法保存的信息,只要对信息进行了一点点的修改,整个信息就会发生翻天覆地的变化,可以很好地保存数据完整性,但是如果中间人对整个原始信息进行修改,还是无法确认,这时候就引入CA证书,通过CA证书对文件再次加密,两者对比,如果相同,则说明没有篡改,已经建立了安全的链接,但是rsa链接的方式,解密加密太慢了,所以,在建立了安全的连接后,再用对称式加密的方式进行加密通讯。
总结:先使用rsa+ca证书验证+hash算法保证数据完整性的方式,建立初步的安全连接,建立安全连接之后发送一个对称式加密的秘钥,通过此秘钥进行接下来的连接
http缓存
从浏览器输入url到页面渲染发生了什么?
为什么输入url就可以展现对应的页面呢?背后经历了什么?
总体为以下几个过程
- DNS解析: 将域名解析成Ip地址
- tcp连接: tcp三次握手
- 发送http请求
- 服务器处理请求并返回http报文
- 浏览器解析渲染页面
- 断开连接:tcp四次挥手
一、DNS域名解析
在浏览器输入网址(URL)后,首先要经过域名解析,因为浏览器只能通过IP地址找到对应的服务器,输入的是域名,那么就需要解析成IP地址。
DNS协议就是通过域名查找IP地址,或者逆向通过IP地址查找域名的服务。 DNS 是一个网络服务器(域名服务器),我们的域名解析简单来说就是在DNS服务器上记录一条信息记录
二、 建立TCP连接(三次握手)
在客户端发送数据之前会发起TCP三次握手用以同步客户端和服务端的序列号的确认号,并交换TCP窗口大小信息。
- 第一次握手,由浏览器发起,告知服务器,我要发送请求了(浏览器发送一个带SYN=1,Seq=x的数据包到服务器)
- 第二次握手,由服务器发起,告知浏览器,我准备接收了,你发送吧(服务器发回一个带SYN=1,ACK= X+1,Seq=Y的响应包以示传达确认信息)
- 第三次握手,由浏览器发起,告知服务器,我马上就要发了,你准备好接收吧(浏览器再传回一个带ACK=Y+1,Seq=Z)
两次就可以建立连接,为什么需要三次握手呢? 为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误
考虑这样子的一种情况,“已失效的连接请求报文段”的产生在这样一种情况下:client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达server。本来这是一个早已失效的报文段。但server收到此失效的连接请求报文段后,就误认为是client再次发出的一个新的连接请求。于是就向client发出确认报文段,同意建立连接。假设不采用“三次握手”,那么只要server发出确认,新的连接就建立了。由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数据。但server却以为新的运输连接已经建立,并一直等待client发来数据。这样,server的很多资源就白白浪费掉了。采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况,client不会向server的确认发出确认。server由于收不到确认,就知道client并没有要求建立连接。”。主要目的防止server端一直等待,浪费资源。
三、发送HTTP请求
TCP三次握手结束建立连接之后,开始发送HTTP请求报文。
请求报文由请求行(request line)、请求头(header)、请求体三个个部分组成
四、服务器处理请求并返回HTTP报文
对于不同用户发送的请求,会结合配置文件,把不同请求委托给服务器上处理相应请求的程序进行处理(例如 CGI 脚本,JSP 脚本,servlets,ASP 脚本,服务器端 JavaScript,或者一些其它的服务器端技术等),然后返回后台程序处理产生的结果作为响应信息。
响应信息会以响应报文的形式返回给客户端,最后浏览器通过渲染引擎将网页呈现在用户面前
响应报文由响应行(request line)、响应头部(header)、响应主体三个部分组成
五、浏览器拿到响应的数据(HTML)后,开始处理渲染页面
浏览器解析渲染页面分为一下五个步骤:
- 根据 HTML 解析出 DOM 树
- 根据 CSS 解析生成 CSS 规则树
- 结合 DOM 树和 CSS 规则树,生成渲染树
- 根据渲染树计算每一个节点的信息
- 根据计算好的信息绘制页面
六、断开连接
- 第一次挥手:由浏览器发起的,发送给服务器,我请求报文发送完了,你准备关闭吧(发起方向被动方发送报文,Fin、Ack、Seq,表示已经没有数据传输了。并进入 FIN_WAIT_1 状态)
- 第二次挥手:由服务器发起的,告诉浏览器,我请求报文接受完了,我准备关闭了,你也准备吧(被动方发送报文,Ack、Seq,表示同意关闭请求。此时主机发起方进入 FIN_WAIT_2 状态。)
- 第三次挥手:由服务器发起,告诉浏览器,我响应报文发送完了,你准备关闭吧(被动方向发起方发送报文段,Fin、Ack、Seq,请求关闭连接。并进入 LAST_ACK 状态。)
- 第四次挥手:由浏览器发起,告诉服务器,我响应报文接受完了,我准备关闭了,你也准备吧(发起方向被动方发送报文段,Ack、Seq。然后进入等待 TIME_WAIT 状态。被动方收到发起方的报文段以后关闭连接。发起方等待一定时间未收到回复,则正常关闭。)
描述几种居中方法
水平垂直居中
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%)
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
//子元素水平垂直居中,需要父元素设置宽高
display: flex;
justify-content: center; //子元素水平居中
align-items: center; //子元素垂直居中
//父元素
display: grid;
//子元素
justify-self:center; //自己本身相对于父元素水平居中
align-self:center; //自己本身相对于父元素垂直居中
HTTP状态码
-
1XX(临时响应,请求正在被处理)
-
2XX(请求成功)
200:请求被成功处理
-
3XX(需要进行重定向)
301:永久重定向
302:临时重定向
304:未修改,不会返回数据 协商缓存命中时返回此状态码,距离上一次请求页面没有发生变化
-
4XX(请求错误,服务器无法处理请求)
401:请求报文中存在语法错误
402:发送的请求需要HTTP认证
403:请求的资源被服务器拒绝
404:服务器上没有请求的资源
-
5XX(服务器处理请求时出错)
500:服务器在处理请求时出现了错误
503:服务器处于超负荷或者维护状态,无法处理请求
伪类和伪元素
伪类是为DOM树中存在的元素添加状态
比如::hover选中鼠标时的状态
伪元素是创建文档中本不存在的元素
JS异步加载/延迟加载
异步加载
defer属性:IE4.0就出现。defer属声明脚本中将不会有document.write和dom修改。浏览器会并行下载其他有defer属性的script。而不会阻塞页面后续处理。注:所有的defer脚本必须保证按顺序执行的。
<script type="text/javascript" defer></script>
async属性:HTML5新属性。脚本将在下载后尽快执行,作用同defer,但是不能保证脚本按顺序执行。他们将在onload事件之前完成。
<script type="text/javascript" async></script>
延迟加载
将 JS 在HTML底部引入,HTML代码时从上往下执行,等到加载JS代码的时候,DOM树已经渲染完毕
使用settimeout延迟引入js
JS数组操作-方法
pop
- 删除数组中的最后一项
- 会改变原数组
- 返回删除的元素
shift
- 删除数组的第一项
- 会改变原数组
- 返回删除的元素
push
- 向数组最后面添加一个元素
- 会改变原数组
filter
- 匹配数组的每一项,将满足条件的项,作为新数组返回,
- 不会改变原数组。
map
- 对数组里面每一个元素调用一个方法,
- 不会改变原数组
foreach
- 对数组里面每一个元素调用一个方法,
- 会改变原数组
promise
promise是ES6中一个新的异步解决方案,解决之前和回调地狱,promise有三个状态
- pending(执行中)
- resolve(执行成功)
- reject (执行失败)
promise只能
从 pending 状态转变为 resolve 或者
从 pending 状态转变为 reject
并且状态转变之后就不会再变
.then()函数接收两个参数,第一个是resolve,第二个是reject
.catch()和.then的第二个参数一样,用于接收reject回调,同时可以接收resolve代码执行过程中抛出的异常。
.then()返回的是一个新的promise实例,因此可以实现链式调用
.then().then().then()即为链式调用
promise.all()
promise.all()接受的参数是一个promise数组,只有当中间的所有promise状态都转变为 resolve 状态时,promise.all()才会进入resolve状态,只要其中有一个promise返回了reject状态,则promise.all返回reject状态,用于某一个异步需要等待多个异步全部执行完成之后才会执行的场景。
排序
冒泡排序:
双层for 循环 比较相邻两个两个元素的大小,交换值;
function bubbleSort(arr) {
for(var i=0;i,arr.length;i++){
for(var j=0;j<arr.length-i-1;j++)
if(arr[j]>arr[j+1]){
var temp= arr[j]
arr[j]=arr[j+1]
arr[j+1]= temp
}
}
}
快速排序:
选择基准,大的放一边,小的放一边,递归
var quickSort = function(arr) {
if (arr.length <= 1) { return arr; }
var pivotIndex = Math.floor(arr.length / 2);
var pivot = arr.splice(pivotIndex, 1)[0];
var left = [];
var right = [];
for (var i = 0; i < arr.length; i++){
if (arr[i] < pivot) {
left.push(arr[i]);
} else {
right.push(arr[i]);
}
}
return quickSort(left).concat([pivot], quickSort(right));
};
vue组件之间
父组件调用子组件的方法
- $refs
- 子组件加上
ref="XXX" - 父组件通过
this.$refs.XXX.method()
- $child
- props
子组件调用父组件的方法
- $parent
- 子组件this.$parent.methods()
开发中可能会出现组件嵌套,可能会出现this.parent.....methods(),不可靠,不建议使用
- $emit 父组件通过@xx监听
兄弟组件
- vuex
CSS
transform图形变化
translate平移
rotate旋转
scale缩放
transition过渡
两点必要内容
- 规定需要把过渡要过加在哪个css属性上
- 时长
例如:
transition: width 3s;当指定的属性开始改变时,添加一个过渡效果
animation动画
animation name
@keyframs name {
}
flex的十二个属性
父元素6个
align-item
justify-content
align-content
flex-flow(flex-direaction和 flex-wrap的简写 默认 flex-flow: row nowrap)
flex-direaction
flex-wrap
子元素6个
order
align-self
flex (flex-basis flex-grow flex-shrink的简写 默认为 flex: 0 1 auto)
flex-basis
flex-grow
flex-shirnk
跳台阶
数组去重
ES6 set方法
let a = [1,2,3,4,5,3,2,1,2]
console.log(Array.from(new Set(a)))
// [1, 2, 3, 4, 5]
不考虑兼容性,这种去重的方法代码最少。但这种方法还无法去掉“{}”空对象
indexOf
双层for循环
call apply bind
深浅拷贝
js中堆内存和栈内存两种存储方式,栈内存的长度固定,堆内存的长度不固定,
基本数据类型都保存在栈内存中,不存在深浅拷贝的问题,
复杂数据类型:对象,由于长度不固定只能保存在堆内存中,但是在栈内存中保存一个指向该对象堆内存地址的指针
浅拷贝 如果直接将一个对象直接赋值给另一个对象,复制的就是这个对象在栈内存中保存的指针,指向同一个堆内存空间,改变其中任意一个对象的值,另一个对象的值也会对应的发生改变
深拷贝 开辟一个新的空间,讲原有对象的属性方法一个一个的复制过来,因为开辟了新的内存空间,这两个对象之间互不干扰,
手写一个深拷贝
function deepCopy(newvalue,oldvalue) {
for(var index in oldvalue){
var item = oldvalue[index]
if(item instanceof Array){
newvalue[index] = []
deepCopy(newvalue[index],item) //递归
}
if(item instanceof Object) {
newvalue[index] = {}
deepCopy(newvalue[index],item) //递归
}
else{
newvalue[index] = item;
}
}
}
科里化实现
new的实现
- 创建一个空对象
- 链接到原型(
obj.__proto__ = Consrtuctor.prototype) - 绑定this
Constructor.apply(obj,arguments) - 返回新对象(如果构造函数有自己retrun时,则返回该值)
//实现一个new
function mynew() {
let obj = {} 创建一个空对象
let Constructor = [].shift.call(arguments) //获取构造函数
obj.__proto__ = Constructor.prototype //将实例对象和构造函数的原型链接起来
let result = Constructor.apply(obj,arguments) //执行constructor为这个新对象添加属性,绑定this
return typeof result === "object" ? result : obj
}
instanceof 的实现
function myinstanceof(firstvalue,secondvalue) {
let fristvalue = fristvalue.__proto__
let secondvalue = secondvalue.prototype
while(true){
if(firstvalue===null)
{
return false
}
if(fristvalue===secondvalue){
return true
}
fristvalue = fristvalue.__proto__
}
}
箭头函数
- 箭头函数没有this,箭头函数里面的this,指向包裹箭头函数的第一个普通函数
- 箭头函数不能做构造函数使用,不能使用new,会报错
- 箭头函数没有arguments对象使用,在箭头函数内不存在
画一个三角形
-
给一个宽高为0的盒子
-
设置边框宽度即可
.triangle {
width: 0px;
height: 0px;
border-bottom: 200px solid #00a3af;
border-left: 200px solid transparent;
border-right: 200px solid transparent;
}
get和post的区别
get传参在URL上直接显示,安全性低,由于URL长度有限制,所以get请求有长度限制
post传参不会再URL上显示,安全性高,不在URL上显示,所以长度对于post来说没有限制
get通常用于无副作用,幂等的请求
post通常用于有副作用,不幂等的情况
get可以缓存
post不能缓存
前端安全
- xss
cross site scripting只将不属于该网站的代码,通过某种方式,让它可以在该网站上执行,一般用于窃取用户cookie
-
csrf
-
点击劫持
攻击者通过iframe将正常的网站引入,然后将iframe设置为透明,故而你点击的时候,以为是点击的你看见的,但实际上点击的都一个透明的iframe,劫持了你的点击事件。
防范方法,禁止内嵌
- js禁止内嵌
- x-frame-option 禁止内嵌
- SQL注入
通过注入SQL查询代码,跳过密码验证,
防范方式:所有的SQL查询语句,使用参数化接口方式,不使用将用户参数插入到SQL查询语句中
-
os注入
-
请求劫持
-
DDoS
大量访问,使其瘫痪,导致正常的用户无法访问
前端性能优化
防抖和节流
防抖
function debounce() {
clearTimeout(timer)
var timer = setTimeout(() => {
},1000)
}
节流
懒加载
SEO
cookie session sessionstorage localstorage
cookie
cookie 是由服务端生成,发送给客户端,cookie分为硬盘型cookie,和内存型cookie,易得硬盘型cookie保存时间较长,内存型cookie保存时间较短,按照时间长短来划分,分为持久性cookie和非持久性cookie,内存型cookie由浏览器维护,
session