盒模型:
基本概念:标准模型 + IE模型
标准模型 和 IE模型的区别
标准盒模型不包括padding和border,IE模型包括paddingh和border-
css如何设置这两种模型
标准盒模型(浏览器默认):box-sizing : content-box
IE盒模型:box-sizing : border-box
- js如何设置获取盒模型对应的宽和高
dom.style.width/height
// 渲染之后的dom,只有IE支持
dom.currentStyle.width/height
// 所有方式都支持
window.getComputedStyle(dom).width/height
实例题(根据盒模型解释边距重叠)
-
BFC(边距重叠解决方案)
- BFC基本概念
- BFC原理:
- 垂直方向的maigin会重叠
解决:建立父级元素,设置overflow:hidden - BFC区域不会与浮动元素发生重叠
- BFC是一个独立容器,外面的元素不会影响到里面的元素
- 浮动元素也包含在BFC元素的高内
- 垂直方向的maigin会重叠
-
如何创建BFC
- float != none
- position != static || relative
- display : inline-blocks,table-cells,table-captions
- overflow 除了 visible 以外的值(hidden,auto,scroll)
BFC使用场景
- 两栏布局:左边宽度固定,右边自适应
<section id="layout">
<style>
#layout{background: red}
#layout .left{
float: left;
width: 100px;
height: 100px;
background: pink
}
#layout .right{
height:110px;
background: #ccc;
/* 将右侧设置成BFC,就不会和浮动元素重叠了 */
overflow: hidden
}
</style>
<div class="left"></div>
<div class="right"></div>
</section>
- 清除浮动:BFC子元素即使是float,也会参与高度计算。
<section id="float">
<style>
#float{
background: red;
/* 父级设置成BFC,即可清除浮动,因为 */
float: left
}
#float .float{
float:left
}
</style>
<div class="float">我是浮动元素</div>
</section>
DOM事件
- 基本概念 :
- DOM事件的级别
// DOM0
element.onclick = function(){}
// DOM2
element.addEventListener('click',function(){},false)
// DOM3,增加了事件类型:鼠标事件,键盘事件
element.addEventListener('keyup',function(){},false)
-
DOM事件模型
- 捕获 : 上 => 下
- 冒泡 : 下 => 上
-
DOM事件流
浏览器在用户交互的过程中,比如点击了左键,从触发到响应的过程。- 捕获 => 目标阶段 => 冒泡:事件通过捕获到达目标元素,从目标元素上升到window
-
描述DOM事件捕获的具体流程(冒泡相反)
- window => document => html => body .... => 目标元素
-
Event对象的常见应用
- event.preventDefault()
- 阻止默认事件,如a标签绑定了click事件,在响应函数中,设置了event.preventDefault()就阻止了a标签的默认跳转行为。
- event.stopPropagation()
- 阻止冒泡。父元素和子元素都绑定了不同的事件,如果不阻止冒泡,单击子元素的时候,按照冒泡的原则,父元素也会被响应,所以在这个情况下需要阻止事件冒泡。
- event.stoplmmediatePropagation
- 一个按钮绑定了两个click事件(1,2),想在1点击的时候不要执行2,默认两个事件都会执行,但是如果在1的响应函数中写event.stoplmmediatePropagation,那么就会成功阻止2的执行。
- event.currentTarget
- 事件委托时,获取父级元素
- event.target
- 事件委托时,获取当前被点击的子元素
- event.preventDefault()
-
自定义事件: CustomEvent
- 应用场景:有一个按钮,触发事件不是通过回调
let eve = new Event('customs')
// ev : DOM节点
ev.addEventListener('custome',function(){
console.log('custome')
})
// 触发事件
ev.dispatchEvent(eve)
HTTP协议
-
HTTP协议主要特点
- 简单快速:资源(图片等)是固定的。
- 灵活:通过一个http协议就可以完成不同数据类型传输。
- 无连接:链接一次就会断掉,不会保持连接。
- 无状态:客户端和服务端是两种状态,完成连接之后就会断开。不记录状态,单从http协议无法区别用户身份。
-
HTTP报文的组成部分
浏览器向服务器请求文件,输入网址后,就是客户端发出请求报文,服务器响应就是响应报文。- 请求报文
- 请求行
- HTTP方法,页面地址,HTTP协议,新协议版本
- 请求头
- key,value值,告诉服务端要什么内容
- 空行
- 告诉服务端往下,该解析请求体了
- 请求体
- 请求行
- 响应报文
- 状态行
- 响应头
- 空行
-
响应体
图示 :
- 请求报文
-
HTTP方法
-
POST和GET的区别
-
HTTP状态码
204 :无内容。服务器成功处理,但未返回内容。
206 :客户发送了一个带有Range头的GET请求,服务器完成了它。
301 :资源(网页等)被永久转移到其它URL
302 :临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI
304 : 未修改。服务器告诉客户端使用缓存。
401 要求身份验证。对于登录后请求的网页,服务器可能返回此响应
403 长时间没操作页面,服务器拒绝请求
405 服务器post 我get了,客户端请求中的方法被禁止
什么是持久链接
HTTP协议采用“请求-应答”模式,当使用普通模式,即非keep-alive模式时,每个请求/应答客户端和服务器都要新建一个连接,完成之后立即断开连接(HTT[协议为无连接的协议)。
当使用keep-alive模式(又成持久连接即HTTP1.1,连接重用)时,keep-alive功能使客户端到服务器端的链接持续有效,当出现对服务器的后继请求时,keep-alive功能避免了简历或者重新建立连接。-
什么是管线化
第二段就是管线化,实在持久链接下完成的。
原型链
- 创建对象有几种方法
// 字面量
let o1 = {name:'o1'}
// 构造函数
let arr = new Array('')
- 原型、构造函数、实例、原型链
原型、构造函数、实例三者关系:- 构造函数 => 原型:声明一个构造函数时,JS引擎会给这个构造函数自动添加一个prototype属性,会初始化一个原型对象。
- 原型如何区分是被哪个构造函数引用的 :原型对象有constructor,指向构造函数。
- 实例 : proto,指向原型对象
o3.__proto__ === M.prototype
原型链:
从一个实例对象往上找构造这个实例的相关联的对象,这个相关联的对象再往上找,还能找到创建它的相关对象,顶端:Object.prototype,这样的一个查找过程。
-
instanceof原理
用来验证对象和构造函数的关系,查看对象是否是构造函数的实例。
实例 instanceof 构造函数
-
new运算符
创建空对象:var o = new Object();
把this指向空对象:A.call(o)
赋值:o.proto = A.prototype
方法中的this指代 new 出来的对象。
var o = new Foo();
//JavaScript 实际上执行的是:
var o = new Object();
o.[[Prototype]] = Foo.prototype;
Foo.call(o);
继承:
- 借助构造函数实现继承
- 缺点 :无法继承方法
function Parent1(){
this.name = 'parent1'
}
function Child1(){
// 继承属性
Parent1.call(this)
// 增加自身属性
this.type = "child1"
}
- 借助原型链实现方法继承
- 缺点 :因为原型链是共用,所以如果多个实例共享,其中一个改变了,另一个也随着改变了。
function Parent2(){
this.name = 'parent2'
}
function Child2(){
this.type = 'child2'
}
Child2.prototype = new Parent2()
- 组合继承:将借用父类构造函数和原型链继承组合,规避了以上两种方法的缺点。
- 缺点:在新建实例化对象的时候,父级被执行了多次。
function Parent3(){
this.name = 'parent3'
this.play = [1,2,3]
}
function Child3(){
// 继承属性
Parent3.call(this)
// 增加自身属性
this.type = 'child3'
}
// 继承方法
Child3.prototype = new Parent3()
//新建实例
let s3 = new Child3()
let s4 = new Child3()
- 组合继承的优化1:
- 缺点:因为是直接引用了父类构造函数,所以constuctor指向的是同一个对象。
function Parent4(){
this.name = 'parent4'
this.play = [1,2,3]
}
function Child4(){
// 继承属性
Parent3.call(this)
// 增加自身属性
this.type = 'child4'
}
// 主要是这句
Child4.prototype = Parent4.prototype
let s5 = new Child4()
let s6 = new Child4()
- 组合继承的优化2:最终版
function Parent5(){
this.name = 'parent4'
this.play = [1,2,3]
}
function Child5(){
// 继承属性
Parent5.call(this)
// 增加自身属性
this.type = 'child4'
}
// 主要是这句:新建了对象,解决了引用同一个对象的问题
Child5.prototype = Object.create(Parent5.prototype)
//修正 construstor,指向自己
Child5.prototype.construstor = Child5
let s5 = new Child5()
let s6 = new Child5()
通信类
-
什么是同源策略及限制
同源策略限制从一个源加载的文档或脚本如何与来自另一个源的资源进行交互,这是一个用于隔离潜在恶意文件的关键的安全机制。- cookie,localStorage和indexxDB无法读取
- DOM无法获得
- AJAX请求不能发送
-
前后端如何通信
- AJAX:同源下
- WebSocket : 不受同源限制
- CORS :支持跨域
-
如何创建AJAX
- XMLHttpRequest对象的工作流程
- 兼容性处理
- 事件的触发条件
- 事件的触发顺序
创建ajax步骤
创建XMLHttpRequest对象,也就是创建一个异步调用对象;
创建一个新的HTTP请求,并指定改HTTP请求的方法、URL以及验证信息;
设置响应HTTP状态变化的函数;
发送HTTP请求;
获取异步调用返回的数据;
使用javascript和DOM实现局部刷新;
var xmlHttpRequest; //定义一个变量用于存放XMLHttpRequest对象
//定义一个用于创建XMLHttpRequest对象的函数
if(window.ActiveXObject){//IE浏览器的创建方式
xmlHttpRequest = new ActiveXObject("Microsoft.XMLHTTP");
}else if(window.XMLHttpRequest){ //Netscape浏览器中的创建方式
xmlHttpRequest = new XMLHttpRequest();
}
//创建ajax对象
var xmlHttp = new XMLHttpRequest();
// open : 填写地址
xmlHttp.open('GET','demo.php','true');
xmlHttp.send()
xmlHttp.onreadystatechange = function(){
if(xmlHttp.readyState === 4 & xmlHttp.status === 200){
}
- 跨域通信的方式
- JSONP
- Hash
- hash改变页面不刷新
- pastMessage
- WebSocket
- CORS
jsonp实现
JSONP的原理是利用script标签的src属性可以进行不受同源策略的限制,进行跨域请求数据的属性,在HTML页面中添加一个script标签,向服务器发送请求,服务器收到请求后,返回数据,将数据放在指定的回调函数中,回调函数中可以对数据进行操作
基本思想:网页通过添加一个元素,向服务器请求JSON数据,这种做法不受同源政策限制;服务器收到请求后,将数据放在一个指定名字的回调函数里传回来。
-
使用jsonp的要素:
- 使用script进行跨域访问
- 回调函数写成全局函数
使用的测试地址: http://suggestion.baidu.com/su?wd=&cb=
- 回调函数写成全局函数
总结 :
- 数据格式必须是:函数名 + (放入数据)==》后端
- 前端必须在全局绑一个函数(一般情况是和数据格式的函数名一致)
- 在需要这些数据的情况下,创建一个script标签,然后把这个标签放到head中,这个时候就等同于在全局中调用了这个函数(异步)。
也就是,后台有具体的一个函数调用,实参就是数据,前端这里需要创建这个函数,然后在需要调用数据的时候,创建一个script标签,src为后端的这个文件,然后将这个标签插入到head里,从创建标签到插入head,这就相当于是调用了这个函数。看到函数名(数据),你就可以认为这是一个jsonp.
原理是:动态插入script标签,通过script标签引入一个js文件,这个js文件载入成功后会执行我们在url参数中指定的函数,并且会把我们需要的json数据作为参数传入。
由于同源策略的限制,XmlHttpRequest只允许请求当前源(域名、协议、端口)的资源,为了实现跨域请求,可以通过script标签实现跨域请求,然后在服务端输出JSON数据并执行回调函数,从而解决了跨域的数据请求。
优点是兼容性好,简单易用,支持浏览器与服务器双向通信。缺点是只支持GET请求。
function createJs(sUrl){
var oScript = document.createElement('script');
oScript.type = 'text/javascript';
oScript.src = sUrl;
document.getElementsByTagName('head')[0].appendChild(oScript);
}
createJs('jsonp.js');
box({
'name': 'test'
});
function box(json){
alert(json.name);
}
安全类
-
CSRF
- 基本概念和缩写:跨站请求伪造
-
原理
用户是网站A的注册用户,登录网站之后,就会下发cookie,保存到用户浏览器中,这样就完成了一个登录过程。
用户又访问了网站B,这个网站中存在一个引诱点击,往往是一个链接,指向一个接口,然后就访问到了A网站,A网站有cookie。重要的是用户在A网站登录过,如果没登录,访问这个接口的时候就会提示登录。
-
攻击构成的条件 :
- 网站A存在接口漏洞
- 用户在A网站登录过
-
防御:
- 加token验证:注册成功或者访问网站之后,服务器会自动为本地存储一个token,在访问不同接口的时候,如果没有带这个token,就不会通过验证。
- referer验证:页面来源,服务器判断是否是本站点下的页面,如果不是直接拦截。
- 隐藏令牌
-
XSS
- 基本概念和缩写:跨域脚本攻击
- 原理 : 不需要用户登录,主要是向页面注入脚本。
两者区别:xss是向页面注入JS运行,在JS函数体里去做要做的事情,CSRF是利用本身漏洞,去执行接口,攻击方式不同,CSRF依赖于用户必须登录网站。
渲染机制
-
什么是DOCTYPE以及作用
文档类型定义。是一系列的语法规则,用来定义XML或XHTML的文件类型。浏览器会使用它来判断文档类型,决定使用何种协议来解析,以及切换浏览器模式。
DOCTYPE是用来生命文档类型和DTD规范的,一个主要的用途便是文件的合法性验证。如果文件代码不合法,那么浏览器解析时便会出一些差错。
从输入网址到渲染页面发生了什么
- 当发送一个URL请求时,不管这个URL是Web页面的URL还是Web页面上每个资源的URL,浏览器都会开启一个线程来处理这个请求,同时在远程DNS服务器上启动一个DNS查询。这能使浏览器获得请求对应的IP地址。
- 浏览器与远程
Web
服务器通过TCP
三次握手协商来建立一个TCP/IP
连接。该握手包括一个同步报文,一个同步-应答报文和一个应答报文,这三个报文在 浏览器和服务器之间传递。该握手首先由客户端尝试建立起通信,而后服务器应答并接受客户端的请求,最后由客户端发出该请求已经被接受的报文。- 一旦
TCP/IP
连接建立,浏览器会通过该连接向远程服务器发送HTTP
的GET
请求。远程服务器找到资源并使用HTTP响应返回该资源,值为200的HTTP响应状态表示一个正确的响应。
此时,Web
服务器提供资源服务,客户端开始下载资源。
第二部分:请求返回后,便进入了我们关注的前端模块- 浏览器会解析
HTML
生成DOM Tree
,其次会根据CSS生成CSS Rule Tree,而javascript
又可以根据DOM API
操作DOM
-
浏览器渲染过程
浏览器会将HTML解析成一个DOM树,DOM 树的构建过程是一个深度遍历过程:当前节点的所有子节点都构建好后才会去构建当前节点的下一个兄弟节点。
将CSS解析成 CSS Rule Tree 。
根据DOM树和CSSOM来构造 Rendering Tree。注意:Rendering Tree 渲染树并不等同于 DOM 树,因为一些像Header或display:none的东西就没必要放在渲染树中了。
有了Render Tree,浏览器已经能知道网页中有哪些节点、各个节点的CSS定义以及他们的从属关系。下一步操作称之为layout,顾名思义就是计算出每个节点在屏幕中的位置。
再下一步就是绘制,即遍历render树,并使用UI后端层绘制每个节点。
重排Reflow
(回流):当浏览器发现某个部分发生了点变化影响了布局,需要倒回去重新渲染,内行称这个回退的过程叫 reflow。reflow 会从 <html> 这个 root frame 开始递归往下,依次计算所有的结点几何尺寸和位置。reflow 几乎是无法避免的。现在界面上流行的一些效果,比如树状目录的折叠、展开(实质上是元素的显 示与隐藏)等,都将引起浏览器的 reflow。鼠标滑过、点击……只要这些行为引起了页面上某些元素的占位面积、定位方式、边距等属性的变化,都会引起它内部、周围甚至整个页面的重新渲 染。通常我们都无法预估浏览器到底会 reflow 哪一部分的代码,它们都彼此相互影响着。-
重绘Repaint
改变某个元素的背景色、文字颜色、边框颜色等等不影响它周围或内部布局的属性时,屏幕的一部分要重画,但是元素的几何尺寸没有变。- 注意:
display:none 的节点不会被加入Render Tree,而visibility: hidden 则会,所以,如果某个节点最开始是不显示的,设为display:none是更优的。
display:none 会触发 reflow,而 visibility:hidden 只会触发 repaint,因为没有发现位置变化。
有些情况下,比如修改了元素的样式,浏览器并不会立刻reflow 或 repaint 一次,而是会把这样的操作积攒一批,然后做一次 reflow,这又叫异步 reflow 或增量异步 reflow。但是在有些情况下,比如resize 窗口,改变了页面默认的字体等。对于这些操作,浏览器会马上进行 reflow。
- 注意:
布局Layout
JS运行机制
单线程 :JS是单线程的,同一时间只能做同一件事。
任务队列:同步任务和异步任务的执行过程。
同步任务:普通JS语句。
异步任务:如定时器等。JS从下到下依次执行,遇到异步任务,就先挂起,不执行,往后执行同步任务,在同步任务执行完毕之后,才会处理异步任务。
Event Loop:事件循环。浏览器的JS引擎遇到异步任务,不会放到运行栈中,会挂起,也不会立即放到异步队列中,同步任务执行完了之后,就会把异步任务放到异步队列中去依次执行。
页面性能
代码层面:避免使用css表达式,避免使用高级选择器,通配选择器。
缓存利用:缓存Ajax,使用CDN,使用外部js和css文件以便缓存,添加Expires头,服务端配置Etag,减少DNS查找等
请求数量:合并样式和脚本,使用css图片精灵,初始首屏之外的图片资源按需加载,静态资源延迟加载。
请求带宽:压缩文件,开启GZIP
-
异步加载
- 异步加载的方式:
- 动态脚本加载
- defer(在script标签加属性)
- async(在script标签加属性)
- 异步加载的方式:
- 异步加载的区别
defer是在HTML解析完之后才会执行,如果是多个,按照加载的顺序依次执行:先执行所有同步任务,后执行有defer属性的script,按照defer顺序执行
async是在加载完之后立即执行,如果是多个,执行顺序和加载顺序无关:先执行所有同步任务,后执行有async属性的script,有async属性的script谁先加载完先执行谁,和顺序无关。
浏览器缓存:
-
区别:前者直接用缓存,后者会和服务器协商。
前端面试之webpack面试常见问题
概念问题一:什么是webpack和grunt和gulp有什么不同
答案:Webpack是一个模块打包器,他可以递归的打包项目中的所有模块,最终生成几个打包后的文件。他和其他的工具最大的不同在于他支持code-splitting、模块化(AMD,ESM,CommonJs)、全局分析。
概念问题二:什么是bundle,什么是chunk,什么是module?
答案:bundle是由webpack打包出来的文件,chunk是指webpack在进行模块的依赖分析的时候,代码分割出来的代码块。module是开发中的单个模块。概念问题三:什么是Loader?什么是Plugin?
答案:
1)Loaders是用来告诉webpack如何转化处理某一类型的文件,并且引入到打包出的文件中
2)Plugin是用来自定义webpack打包过程的方式,一个插件是含有apply方法的一个对象,通过这个方法可以参与到整个webpack打包的各个流程(生命周期)。
配置问题:如何可以自动生成webpack配置?
答案: webpack-cli /vue-cli /etc ...脚手架工具开发问题一:webpack-dev-server和http服务器如nginx有什么区别?
答案:webpack-dev-server使用内存来存储webpack开发环境下的打包文件,并且可以使用模块热更新,他比传统的http服务对开发更加简单高效。开发问题二:什么 是模块热更新?
答案:模块热更新是webpack的一个功能,他可以使得代码修改过后不用刷新浏览器就可以更新,是高级版的自动刷新浏览器。优化问题一:什么是长缓存?在webpack中如何做到长缓存优化?
答案:浏览器在用户访问页面的时候,为了加快加载速度,会对用户访问的静态资源进行存储,但是每一次代码升级或是更新,都需要浏览器去下载新的代码,最方便和简单的更新方式就是引入新的文件名称。在webpack中可以在output纵输出的文件指定chunkhash,并且分离经常更新的代码和框架代码。通过NameModulesPlugin或是HashedModuleIdsPlugin使再次打包文件名不变。优化问题二:什么是Tree-shaking?CSS可以Tree-shaking吗
答案:Tree-shaking是指在打包中去除那些引入了,但是在代码中没有被用到的那些死代码。在webpack中Tree-shaking是通过uglifySPlugin来Tree-shaking
JS。Css需要使用Purify-CSS。