# 很久很久以前的面试复习一
# 杂谈
jquery 源码: 核心架构,事件委托,插件机制
项目开发中遇到过什么难题,怎么解决的~
npm 常用命令 webpack
自我陈述准备:把我面试的沟通方向,阔达、自信的适度发挥
简历: 左右和纵向分栏,项目做完之后的公司收益和技术收益,兴趣说技术相关兴趣
遇到不懂的问题,可以说指导,回去思考,好奇,不要说不知道,不懂,没经历过结尾,要资料,再来~
自如谈兴趣,巧妙示实例,适时讨疑问,节奏要适宜,切忌小聪明
# 三栏布局
布局:高度已知,左右固定,中间自动:浮动,绝对定位,弹性盒子,display:table-cell,网格布局,然后其各自有什么优缺点,假设高度已知去除会怎么样?如果有一个高度比较高,撑开了,别的跟着撑开(flex和table可以用)?这五种方案的兼容性如何?最优方案是哪个?最后:BFC,圣杯和双飞翼布局,以及felx布局
布局小结:语义化掌握到位,页面布局理解深刻,CSS基础知识扎实,思维灵活且积极向上,代码规范
布局变通: 三栏布局:左右宽度固定,中间自适应; 上下高度固定,中间自适应。 两栏布局:左宽固定,右自适应; 右宽固定,左自适应; 上高度固定,下自适应;下高度固定,上自适应~
# CSS盒模型:谈谈你对CSS盒模型的认识:
1、 border、margin、padding、content,标准模型和IE模型 2、 标准模型和IE模型的区别 3、 CSS如何设置这两种模型 4、 JS如何设置获取盒模型对应的宽和高: dom.style.width/height--只能获取行内(内联)样式的宽高 dom.currentStyle.width/height--渲染以后的样式,只有IE支持 window.getComputedStyle(dom).width/height--兼容性好,对比第二种 dom.getBoundingClientRect().width/height--常用来计算元素对于视口的位置(top,left,right,bottom,width,height) 5、 根据盒模型解释边距重叠 6、 BFC边距重叠解决方案
BFC的基本概念:块级格式化上下文,它是指一个独立的块级渲染区域,只有Block-level BOX参与,该区域拥有一套渲染规则来约束块级盒子的布局,且与区域外部无关。
BFC的生成:CSS2.1中规定满足下列CSS声明之一的元素便会生成BFC:
- 根元素(html本身就是BFC)
- float的值不为none
- overflow的值不为visible
- display的值为inline-block、table-cell、table-caption
- position的值为absolute或fixed
BFC的约束规则(原理):
- 内部的Box会在垂直方向上一个接一个的放置
- 垂直方向上的距离由margin决定。(完整的说法是:属于同一个BFC的两个相邻Box的margin会发生重叠,与方向无关,给子元素再加一个父元素,父元素创建一个BFC即可解决)
- 每个元素的左外边距与包含块的左边界相接触(从左向右),即使浮动元素也是如此。(这说明BFC中子元素不会超出他的包含块,而position为absolute的元素可以超出他的包含块边界)
- BFC的区域不会与float的元素区域重叠(一个固定宽度浮动,一个只设高度且创建BFC即可)
- 计算BFC的高度时,浮动子元素也参与计算(创建BFC清除浮动原理,例如:子元素浮动,父元素overflow:auto)
- BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面元素,反之亦然
# DOM事件类
基本概念:DOM事件的级别(例如:DOM2的事件)
- DOM0 element.onclick=function(){}
- DOM2 element.addEventListener('click',function(){},false)
- DOM3 element.addEventListener('keyup',function(){},false)
DOM事件模型(捕获和冒泡)
DOM事件流 (捕获阶段=>目标阶段=>冒泡阶段)
描述DOM事件捕获的具体流程(window->document->html(document.documentElement)->body->...->目标元素),冒泡相反
Event对象的常见应用
- event.preventDefault()
- event.stopProagation()
- event.stopImmediatePropagation() //同一个元素绑定两个点击事件,可阻止一个事件触发
- event.currentTarget //当前所绑定的事件,测试
- event.target
自定义事件
var eve = new Event('custome');
element.addEventListener('custome',function(){
console.log('custome')
});
element.dispatchEvent(eve);
//CustomEvent 可以传入obj数据:
var eve2 = new CustomEvent('custome2',obj);
element.addEventListener('custome2',function(){
console.log('custome')
});
element.dispatchEvent(eve2);
2
3
4
5
6
7
8
9
10
11
12
# HTTP协议类
- HTTP协议的主要特点
- 简单快速,灵活,无连接,无状态
- HTTP报文的组成部分
- 请求报文:请求行、请求头、空行、请求体
- 相应报文:状态行、响应头、空行、响应体
- HTTP方法
- GET->获取资源
- POST->传输资源
- PUT->更新资源
- DELETE->删除资源
- HEAD->获得报文首部
- PATCH->对资源进行部分修改
- OPTIONS->查询支持的方法
- CONNECT->要求在与代理服务器通信时建立隧道
- TRACE->追踪路径
- POST和GET的区别
- GET在浏览器回退时是无害的,而POST会再次请求
- GET产生的URL地址可以被收藏,而POST不可以
- GET请求会被浏览器主动缓存,而POST不会,除非手动设置
- GET请求只能进行URL编码,而POST支持多种编码方式
- GET请求参数会被完整保存在浏览器历史纪录里,而POST中的参数不会被保留
- GET请求在URL中传输的参数是有长度限制的,而POST没有限制
- 对参数的数据类型,GET只接受ASCLL字符,而POST没有限制
- GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息
- GET参数通过URL传递,POST放在Request body中
- GET和POST本质上就是TCP链接,并无差别。但是由于HTTP的规定和浏览器/服务器的限制,导致他们在应用过程中体现出一些不同。
- GET产生一个TCP数据包;POST产生两个TCP数据包。
- HTTP状态吗
- 1XX 指示信息-表示请求已被接收,继续处理
- 2XX 成功-表示请求已被成功接收并成功进行了处理
- 3XX 重定向-要完成请求必须进行更进一步的操作
- 4XX 客户端错误-请求有语法错误或请求无法实现
- 5XX 服务器错误-服务端未能正常处理客户端的请求而出现意外错误
- 什么是持久连接
- HTTP协议采用“请求-应答”模式,当使用普通模式,即非Keep-Alive模式时,每个请求/应答客户端和服务器都需要新建一个连接,完成之后立即断开连接(HTTP协议为无连接协议)
- 当使用Keep-Alive模式(又称持久连接、连接复用)时,Keep-Alive 功能使客户端到服务器端的连接持续有效,当出现对服务器的后继请求时,Keep-Alive功能避免了建立或者重新建立连接
- 什么是管线化
- 在使用持久连接的情况下,某个连接上的消息传递类似于:请求1->响应1->请求2->响应2->请求3->响应3
- 某个连接上的消息变成了类似这样:请求1->请求2->请求3->响应1->响应2->响应3
- HTTP缓存
# 原型链类
- 创建对象有几种方法(3种)
- var o1 = {name:'o1'};var o11 = new Object({name:'o11'});
- var M = function(){this.name='o2'};var o2 = new M();
- var P = {name:'o3'};var o3 = Object.create(P);
- 原型、构造函数、实例、原型链
- instanceof原理
- 沿着A的_proto_这条线来找,同时沿着B的prototype这条线来找,如果两条线能找到同一个引用,即同一个对象,那么就返回true。如果找到终点还未重合,则返回false。
- new运算符
- 创建一个新空对象
- 空对象继承(指向)构造函数的prototype原型对象
- 构造函数被执行,上下文this会被指定到这个新实例对象上
- 如果构造函数返回了一个“对象”,那么这个对象会取代new出来的对象。如果构造函数没有返回对象,那么new出来的结果为步骤一创建的新对象。
//new运行原理
var new2 = function(func){
var o = Object.create(func.prototype); //创建空对象,空对象关联构造函数的原型链
var k = func.call(o); //执行构造函数
if(typeof k === 'object'){ //判断结果是不是对象类型
return k;
}else{
return o;
}
}
2
3
4
5
6
7
8
9
10
//通过原型继承创建一个新对象
function inherit(proto){
if(proto == null) {throw TypeError()};
if(Object.create()) return Object.create(proto);
var t = typeof(proto);
if(t !== 'object' && t !== 'function') throw TypeError();
var F = function(){};
F.prototype = proto;
return new F();
}
2
3
4
5
6
7
8
9
10
# 面向对象类
# 类与实例
- 类的声明
- 生成实例
//构造函数的方式继承
function Animal(){
this.name = 'name';
}
//ES6的方式
class Animal2{
constructor(){
this.name = 'name';
}
}
//实例化,声明方式不一样,但是实例化方式是一样的
console.log(new Animal(),new Animal2())
2
3
4
5
6
7
8
9
10
11
12
13
14
# 类与继承
- 如何实现继承
- 继承的几种方式
//借助构造函数实现继承
function Parent1(){
this.name = 'parent1'
}
function Child1(){
//在子类中执行需继承的构造函数
//这样就改变了Parent1()的this指向
//从而导致了父类执行的属性都会挂载到子类的实例上去
Parent1.call(this);
this.type = 'child1'
}
console.log(new Child1)//没有参数可以不写小括号
//缺点:Parent1原型链上的方法没有办法被继承,只实现了部分继承
//无法实现函数复用,每个子类都有父类实例函数的副本,影响性能
2
3
4
5
6
7
8
9
10
11
12
13
14
//借助原型链继承
function Parent2(){
this.name = 'parent2';
}
function Child2(){
this.type = 'child2'
}
//让构造函数的实例能访问到父类的原型对象上的属性和方法
//Parent2的实例赋值给 Child2.prototype 属性
//new Child2().__proto__ => Child2.prototype == new Parent2()
Child2.prototype = new Parent2();
console.log(new Child2())
//缺点:来自原型对象的引用属性是所有实例共享的,child1.__proto__==child2.__proto__
//无法实现多继承
//创建子类实例时,无法向父类构造函数传参
//要想为子类新增属性和方法,必须要在new Animal()这样的语句之后执行,不能放到构造器中
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//组合继承
function Parent3(){
this.name = 'parent3';
this.paly = [1,2,3];
}
function Child3(){
Parent3.call(this);
this.tpye = 'child3'
}
Child3.prototype = new Parent3();
var s3 = new Child3();
var s4 = new Child3();
s3.paly.push(4);
console.log(s3.play,s4.paly);
//缺点:父级构造函数实例化了两次~
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//组合继承优化1
function Parent4(){
this.name = 'parent4';
this.paly = [1,2,3];
}
function Child4(){
Parent4.call(this);
this.tpye = 'child4'
}
Child4.prototype = Parent4.prototype; //引用同一个对象,导致constructor相同
var s5 = new Child4();
var s6 = new Child4();
s3.paly.push(4);
console.log(s5.play,s6.paly);
console.log(s5 instanceof Child4,es5 instanceof Parent4)//true true //无法区分是父类(Parent4)还是子类(Child4)实例化的
console.log(s5.constructor) //Parent4 引用导致,这不是我们想要的
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//组合继承优化2
function Parent5(){
this.name = 'parent5';
this.paly = [1,2,3];
}
function Child5(){
Parent5.call(this);
this.tpye = 'child5'
}
Child5.prototype = Object.create(Parent5.prototype);
//Object.create原理:创建空对象,空对象关联构造函数(Parent5)的原型链
child5.prototype.constructor = Child5; //还是需要指定constructor
var S7 = new Child5();
console.log(s7 instanceof Child5,s7 instanceof Parent5)//true true
console.log(s7.constructor) // Child5
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- 其它继承方式:
//实例继承
function Parent6(){
this.name = 'parent2';
}
function Child6(name){
var parent = new Parent6();
parent.name = name || 'Tom';
return parent;
}
//实例是父类的实例,不是子类的实例
//无法实现多继承
2
3
4
5
6
7
8
9
10
11
//拷贝继承
function Parent7(){
this.name = 'parent7';
}
function Child7(name){
var parent = new Parent7();
for(var p in parent){
Child6.prototype[p] = parent[p];
}
Cat.prototype.name = name || 'Tom';
}
//效率较低,内存占用高
//无法获取父类不可枚举的方法
2
3
4
5
6
7
8
9
10
11
12
13
# 通讯类
- 什么是同源策略及限制
- 同源策略限制从一个源加载的文档如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的关键安全机制。(http协议,域名,端口)
- 主要限制在:cookie,localStrage和IndexedDB无法读取;DOM无法获得,Ajax无法发送
- 前后端如何通讯
- ajax,websocket,CORS,EventSource,服务端渲染
- 如何创建Ajax
- XMLHttpRequest对象的工作流程
- 兼容性处理(IE)
- 事件的触发条件
- 事件的触发顺序
- 跨域通讯的几种方式
- JSONP
- Hash
- postMessage
- websocket
- CORS
- window.name
- window.domain
# 安全类
- CSRF 跨站请求伪造
- 基本概念和缩写
- cross-site request forgery
- 攻击原理
- 登陆过A网站
- 在访问B网站时,B网站诱使点击连接访问A网站(通过对A网站还存在的cookie等身份验证)
- 防御措施
- Token验证, 访问接口时候带token
- Referer验证 页面来源,同域
- 隐藏令牌 类似于token,例如隐藏在头部
- 输入验证码
- 基本概念和缩写
- XSS 跨域脚本攻击
- 基本概念和缩写
- cross-site scripting
- 攻击原理
- 向页面注入脚本运行,脚本中做攻击内容,通过input,textarea等标签,例如输入评论内容的时候
- 危害:窃取用户的 Cookie 值;伪造虚假的输入表单骗取个人信息;显示伪造的文章或者图片
- 防御措施
- 过滤标签符号'< >'等
- 设置 Cookie 为 HttpOnly
- 基本概念和缩写
- SQL注入
- 基本概念
- 服务器上的数据库运行非法的 SQL 语句,主要通过拼接来完成。
- 攻击原理
- 在搜索或查询等SQL查询时,拼接非法SQL查询隐藏数据或者本不可以显示的内容等
- 防范手段
- 使用参数化查询
- 单引号转换
- 基本概念
- DOS 拒绝服务攻击
- 原理
- 其目的在于使目标电脑的网络或系统资源耗尽,使服务暂时中断或停止,导致其正常用户无法访问。
- 原理
# 算法类
- 排序
- 快速排序 https://segmentfault.com/a/1190000009426421
- 选择排序 https://segmentfault.com/a/1190000009366805
- 希尔排序 https://segmentfault.com/a/1190000009461832
- 堆栈、队列、链表 https://juejin.im/entry/58759e79128fe1006b48cdfd
- 递归 https://segmentfault.com/a/1190000009857470
- 波兰式和逆波兰式
- http://www.cnblogs.com/chenying99/p/3675876.html
- https://github.com/Tairraos/rnp.js/blob/master/rpn.js
技巧:
- 伪代码
- 找面试官要提示
- 用了什么算法,原理
# 渲染机制
- 什么是DOCTYOE及作用
- DTD文档类型定义,用来定义XML或者(X)HTML的文件类型。浏览器使用它来判断文档类型,决定使用何种协议来解析,以及切换浏览器模式。
- DOCTYOE是用来声明文档类型和DTD规范的,一个主要用途就是验证文件的合法性。
- HTML5 <!DOCTYPE html>
- HTML 4.01 Strict
- HTML 4.01 Transitional
- 浏览器渲染过程
- 重排Reflow
- DOM结构中的各个元素都有自己的盒子(模型),这些都需要浏览器根据各种样式来计算并根据计算结果将元素放到它该出现的位置,这个过程称为reflow
- 重绘Repaint
- 当盒子的位置、大小及其他属性都确认后,浏览器于是便把这些元素都照各自的特性绘制了一遍,于是页面的内容出现了,这个过程为repaint
- 布局Layout
# js运行机制
- 理解JS的单线程的概念
- 理解任务队列
- 理解Event Loop
- 理解哪些语句会放入异步任务队列
- setTimeout和setInterval
- DOM事件
- ES6中的Promise
- 理解语句放入异步任务队列的时机
- 时间计算到了才放入异步队列
# 页面性能类
提升页面性能的方法有哪些?
资源压缩合并,减少HTTP请求
非核心代码异步加载->异步加载的方式->异步加载的区别
- 异步加载的方式:1、动态脚本加载;2、defer;3、async
- 异步加载的区别:1、defer是在HTML解析完以及同步js执行完之后才会执行,如果是多个,安装加载的顺序依次执行;2、async是在加载完成之后立即执行,如果是多个,执行顺序和加载顺序无关。
利用浏览器缓存->缓存的分类->缓存的原理
- 强缓存:Expires (Expires:Thu,21 Jan 2017 23:39:02) GMT;Cache-Control (Cache-Control:max-age=3600)
- 协商缓存:Last-Modified If-Modified-Since Etag If-None-Match (Last-Modified:Web,26 Jan 2017 00:35:11 GMT)
- Expires是绝对时间,取客户端电脑的时间来对比,可能不准确,而且可能被修改,Cache-Control是相对时间
- Last-Modified 与 If-Modified-Since的值相同,Last-Modified是服务器下发的时间,If-Modified-Since是客户端触发协商缓存,请求询问服务器带入的请求头中。这个方式的协商缓存有一个缺点,有可能文件改动了,但是内容没变,所有才有了Etag
- Etag是服务器下发的key值(Hash值),If-None-Match是客户端触发协商缓存,请求询问服务器key值(内容)有没有变化,是否可以使用缓存。
使用CDN(3~4个域名cdn,并行加载)
预解析DNS
<meta http-equiv="x-dns-prefetch-control" content="on"> //强制打开dns预解析,a标签默认开启,但是https情况下是一般是关闭的
<link ref="dns-prefetch" href="XXX">
优化分类:
- 网络层面
- 构建层面
- 浏览器渲染层面
- 服务端层面
优化方式:
- 资源的合并与压缩
- 压缩 html,css,js
- 资源合并:公共库合并,业务分离,不同页面的合并,见机行事,随机应变
- 图片编解码和类型选择
- 不同场景选择不同格式图片
- 雪碧图大小要合适,同页面的图片,并且小于一定大小的合并
- 浏览器的渲染机制
- 顺序执行、并发加载,域名并发限制(3~4个cdn域名并发加载)
- 是否阻塞
- 依赖关系
- 引入方式(css阻塞js的运行,但是不阻止js加载)
- 重绘与回流,图层(将频繁重绘回流的 DOM 元素单独作为一个图层,但是图层也不能过多)
- 创建图层的方式:
- 3D 或透视变换 css 属性
- 使用加速视频解码的 video 节点
- 拥有 3D(webGL)上下文或加速的2D 上下文 canvas 节点
- 混合插件(如Flash)
- 对自己的 opacity 做 CSS 动画或使用一个动画 webkit 变换的元素
- 拥有 css 过滤器的元素
- 元素有一个包含复合层的后代节点
- 元素有一个 z-index 较低且包含一个符合层的兄弟元素
- 懒加载预加载
- 浏览器存储
- 缓存机制
- PWA
- Vue-SSR
请求过程中潜在的性能优化点(理解http请求过程是核心):
- dns 是否可以通过缓存减少 dns 查询时间?
- 网络请求的过程走最近的网络环境?
- 相同的静态资源是否可以缓存?
- 能否减少 http 请求的大小?
- 减少 http 请求
- 服务端渲染
# 错误监控
- 前端错误的分类
- 即时运行错误:代码错误
- 资源加载错误
- 错误的捕获方式
- 即时运行错误:try...catch 和 window.onerror
- 资源加载错误:object.onerror(在节点上绑定onerror,该错误不会冒泡)、performance.getEntries()和Error事件捕获(window.addEventListener('error',function(e){console.log('捕获',e)},true))
延伸:跨域的JS运行错误可以捕获吗?错误提示是什么?怎么处理?
- 在script标签增加crossorigin属性
- 设置JS资源响应投Access-Control-Allow-Origin:*
- 上报错误的基本原理
- 采用Ajax通信的方式上报
- 利用Image对象上报(new Image()).src='接口地址'
# 业务能力
- 准备要充分
- 项目背后的原理和技术难点
- 描述要演练
- 我做过什么业务
- 负责的业务有什么业绩
- 使用了什么技术方案
- 突破了什么技术难点
- 遇到了什么问题
- 最大的收获是什么
- 引导找时机
- 优势要发挥
- 回答要灵活
# 团队协作能力与带人能力
# 职业竞争力
- 乐观积极
- 主动沟通
- 逻辑顺畅
- 上进有责任心
- 有主张,做事果断
# 职业规划
- 职业竞争力
- 业务能力
- 思考能力
- 学习能力
- 无上限付出
- 学会赞美
- 职业规划
- 目标是什么
- 在业务上成为专家,在技术上成为行业大牛
- 进阶的目标
- 不断的学习积累个方面经验,以学习为主
- 长期目标
- 做几件有价值的事情,如开源作品、技术框架
- 方式方法
- 先完成业务上的主要问题,做到极致,然后逐步向目标靠拢
- 目标是什么
# 面试总结
- JD描述
- 对于社招一定要看
- 简历
- 对照JD改写出相吻合的简历,对于未掌握的技术栈快速复习、理解
- 自我介绍
- 一定要打草稿,展示什么优势、描述什么项目,切忌临场发挥