总结了一些前端的相关面试题
http://ovenzeze.coding.me/
菜鸟教程前端面试题
2018春招-头条,腾讯,小米,百度面经
https://www.cnblogs.com/itlkNote/p/6831115.html
https://wenku.baidu.com/view/cbded359326c1eb91a37f111f18583d049640f99.html
https://github.com/h5bp/Front-end-Developer-Interview-Questions/blob/master/Translations/Chinese/README.md
解题套路
- 抽象的问题,通过举例子来说明
- 遇到不会的,转移话题到会的内容,比如:不了解async/await,就和面试官说,我平时处理异步用的是Promise,然后把话题转到Promise的知识
- 侃侃而谈,讲述这项技术的历史发展
HTML考题
DOCTYPE的作用
<!DOCTYPE>
用于告知浏览器的解析器用什么文档标准来解析这个文档。DOCTYPE不存在或格式不正确会导致文档以兼容模式呈现。
HTML5的写法<!DOCTYPE HTML>
如何理解 HTML 语义化
目的:
- 对人友好:标签语义化就是给某块内容用上最恰当合适的标签,使其通俗易懂;
- 对搜索引擎友好:使搜索引擎能够更方便地识别页面的每个部分
方法1 举例子:
- 块元素:头部用 header,nav导航,章节用 section,段落用 p,边栏用 aside,主要内容用 main
- 行内元素:span,a链接,b加粗,i斜体,time时间,progress进度条
注意!!input,button等元素是inline-block元素
方法2 讲发展历史:
最开始是 PHP 后端写 HTML,不会 CSS,于是就用 table 来布局。table 使用展示表格的。严重违反了 HTML 语义化。
后来有了专门的写 CSS 的前端,他们会使用 DIV + CSS 布局,主要是用 float 和绝对定位布局。稍微符合了 HTML 语义化。
再后来,前端专业化,知道 HTML 的各个标签的用法,于是会使用恰当的标签来展示内容,而不是傻傻的全用 div,会尽量使用 h1、ul、p、main、header 等标签
语义化的好处是易读、有利于SEO等。
meta viewport 是做什么用的,怎么写?
方法1 举例子:
方法2 侃侃而谈:
一开始,所有页面都是给PC准备的,乔布斯推出 iPhone 3GS,页面是不适应手机屏幕的,所以乔布斯的工程师想了一个办法,默认把手机模拟成 980px,页面缩小。
后来,智能手机普及,这个功能在部分网站不需要了,所以我们就用 meta:vp 让手机不要缩小我的网页。
canvas 元素是干什么的?
把画板项目丢给他
看 MDN 的 canvas 入门手册
替换元素和非替换元素
img,input等自闭和标签都是替换元素,这些元素没有实际的内容,即是个空元素<div>内容</div>
这种内部可以有内容的都是非替换元素,他们将内容直接告诉浏览器,将其显示出来
css考题
选择器的权重和优先级
第一等:内联样式,如: style=””,权值为1000。
第二等:ID选择器,如:#content,权值为100。
第三等:属性选择器和伪类,如.content,:hover,[attribute]权值为10。
第四等:元素选择器和伪元素选择器,如div p,权值为1。
同样优先级,写在后面的覆盖前面的。
特殊的!important优先级最高
说说css盒模型
盒模型包括content、padding、border、margin
但width和height不包括margin
标准盒模型(https://developer.mozilla.org/zh-CN/docs/Web/CSS/CSS_Box_Model/Introduction_to_the_CSS_box_model)
设置 box-sizing:
- content-box: width/height == 内容区宽度/高度 【标准盒模型】
- border-box: width/height == 内容区宽度/高度 + padding 宽度/高度 + border 宽度/高度 【IE盒模型】
js如何获取盒模型的宽和高
- el.style.width/height 【只能取到行间样式,结果带单位】
getComputedStyle(el).width/height 【获取最终计算后得到的样式,结果带单位】
12var x = getComputedStyle(box).width;console.log(x); //100pxel.getBoundingRect().width/height 【结果不带单位,且包含border】
12var x = box.getBoundingClientRect().width;console.log(x) //102 【width + 左右border】
css reset 和 normalize.css 有什么区别?
- reset 重置,之前的样式我都不要了,抛弃默认样式
- normalize 使标准化, 让所有浏览器的标签都跟标准规定的默认样式一致,各浏览器上的标签默认样式基本统一。
如何居中
尽量能写多少就写多少,让面试官看到你不仅熟悉css布局,而且很有探讨精神,竟然会多种布局方式
https://www.jianshu.com/p/841b9f395b8e
绝对定位50% + 负的margin【必须知道子元素的宽高,不然没法设置负的margin】
【点击查看代码】
绝对定位全为0,margin:auto【必须知道子元素的宽高】
【点击查看代码】
绝对定位 + calc【必须知道子元素的宽高】
【点击查看代码】
绝对定位50% + transform:translate(-50%,-50%)【不需要知道子元素宽高】
【点击查看代码】
flex布局
水平X居中
- inline元素:爸爸身上写 text-align:center;
- 块元素【必须设置width】:margin:0 auto;
垂直Y居中
https://jscode.me/t/topic/1936
line-height === height
多行文本垂直居中
父元素设置display:table
,子元素设置display:table-cell;vertical-align:middle
BFC 是什么?
块级格式化上下文(Block Formatting Contexts)
举例子:
- 给爸爸overflow:hidden 清除浮动。(但我平常总是用 .clearfix 清除浮动)
- 外边距合并,给爸爸添加overflow:hidden 取消父子 margin 合并(给儿子设置margin-top时,爸爸也会被顶下去)
BFC的原理
- 在同一个BFC内的两个相邻Box的margin会发生重叠
- BFC的区域不会与float box重叠
- BFC在页面上是一个独立的容器,容器里面的子元素不会影响到外面的元素。反之也如此。
- 计算BFC的高度时,浮动元素也参与计算
哪些元素会生成BFC
- 根元素
- float属性不为none
- position为absolute或fixed
- display为inline-block, table-cell, table-caption, flex, inline-flex
- overflow不为visible【overflow:auto/hideen生成BFC】
line-height=150%和1.5的区别
150%是根据父元素的字体大小计算出行高,并且子元素依然沿用这个计算后的行高。而1.5则是根据子元素自己字体的大小去乘以1.5来计算行高。另,1.5em等也是按照150%的情况来算的。
float布局的缺点
浮动布局,浮动元素脱离文档流,需要做清除浮动,这个处理不好的话,会带来很多问题,比如高度塌陷等。
如何清除浮动?
看笔记
- 方法1: overflow:hidden
- 方法2 给父级加上class=”clearfix” 12345678.clearfix:after{content:'';display:block;clear:both;}.clearfix{zoom:1; /*兼容低版本IE*/}
position定位
- static:默认值,即没有定位
- relative:相对于其原来的位置【导致自身位置发生相对变化,而不影响其他元素的位置】;原本所占的块空间不会改变。
- absolute:相对于最近的已定位父元素(不为static的父元素),如果元素没有已定位的父元素,那么它的位置相对于
<html>
;absolute会脱离文档流;absolute具有“包裹性”,块元素在没有设置宽度的情况下,不再单独占满一行,而是宽度由内容决定 - fixed:与absolute相同,除了fixed是相对于浏览器窗口或frame进行定位。
- sticky:粘性定位,该定位相对于用户滚动的位置。
rem和em的区别
任意浏览器的默认字体高都是16px,最小12px。所有未经调整的浏览器都符合: 1em=16px。
em是相对于自身font-size进行计算的,自身没有设置font-size的话则继承自父元素的字体大小
rem(root em,根em),是根据HTML根元素字体大小进行计算的
css3
animation的api:
语法:animation: name duration timing-function delay iteration-count direction fill-mode play-state;
https://www.runoob.com/cssref/css3-pr-animation.html
如何用transform开启手机加速?
我们平常会使用left和top属性来修改节点的位置,但left和top会触发重reflow,代价相当大。取而代之的更好方法是使用translate,这个不会触发reflow
translateZ(0)或者translate3d(0,0,0) 开启GPU加速
transition 和 animation 的区别
transition
是过渡,表示一个状态过渡到另一个状态animation
是动画,可以设置关键帧,一个动画可以由多个关键帧多个过渡组成,另外,animation
可以设置infinite
,暂停等
reflow重排/回流
回流是布局或者几何属性需要改变就称为回流。
回流必然导致重绘,重绘不一定会引发回流。
当你增加、删除、修改DOM节点时
当你移动DOM的位置
当你修改css尺寸(比如宽、高、display)
当你修改网页默认字体时
repaint重绘
重绘是当节点需要更改外观而不会影响布局的,比如改变 color,改变背景色 就称为重绘
当你需要往页面中插入10个<li>
时,你可以:
通过文档碎片,或者拼接完成字符串后,再一次性塞入innerHTML,这样可以降低Repaint(因为它不是每次都触发Repaint,而是一次性打包Repaint)
requestAnimationFrame
浏览器是 60Hz 的刷新率,每 16ms 才会更新一次。
requestAnimationFrame的方式的优势如下:
- 经过浏览器优化,动画更流畅
- 窗口没激活时,动画将停止,省计算资源
- 更省电,尤其是对移动终端
requestAnimationFrame的用法与settimeout很相似,只是不需要设置时间间隔而已。
|
|
|
|
cancelAnimationFrame(timer)可以取消动画
移动端布局
mata:viewport
- @media媒体查询
- js动态设置html字体大小 + dom元素使用rem单位 = 动态rem
- 100vh == 视口高度,100vw == 视口宽度
js考题
7种数据类型[6种值类型 + 引用类型object]
原始类型/值类型:
number,string,boolean,symbol,null,undefined
引用类型:
object
typeof的结果
typeof的两个bug
- typeof 函数 //function,正确的应该是object
- typeof null //object,null不是object,它是7种数据类型之一
- typeof console.log(1) //打印出1,然后类型为’undefined’,因为console返回undefined
- typeof console.log // function
- typeof 数组 //object
- typeof null //object,【!!null是7种数据类型之一,它不是object,这是js遗留的历史bug】
- typeof 函数//function 【!!function在7种数据类型中,属于object】
- typeof NaN //number 【NaN表示非数字的数字类型】
|
|
判断是否是数组类型
|
|
instanceof可以判断实例对象的构造函数
伪数组变成数组
|
|
判断是否是空对象{}
用 JSON.stringify(obj)
function的length
函数的length值就是它的参数数量
js中的内置函数(可以通过new的函数)
- Number
- String
- Boolean
- Object
- Array
- Function
- Date
- RegExp
- Error
==与===
|
|
必须用===,那么什么时候用==
|
|
js的垃圾回收机制
js具有自动垃圾回收机制。垃圾收集器会按照固定的时间间隔周期性的清理一下,释放内存。
垃圾回收方式是:标记清除、计数引用(该方法已经过时)。
原理:当变量进入环境时,将这个变量标记为“进入环境”。当变量离开环境时,则将其标记为“离开环境”。标记“离开环境”的就回收内存。
工作流程:
- 垃圾回收器,在运行的时候会给存储在内存中的所有变量都加上标记。
- 然后去掉环境中的变量以及被环境中的变量引用的变量(闭包)的标记。
- 剩下含有标记的会被视为准备删除的变量。
- 垃圾回收器完成内存清除工作,销毁那些被标记的值释放内存空间。
js运行机制
js是单线程的,同一时间只能做一件事。
同步和异步的区别
举例:点外卖
由于js是单线程运行的,如果同步会阻塞代码执行,异步则不会阻塞代码执行
一个ajax请求,由于网络慢,需要5s钟,如果是同步的,这5s页面就卡死在这了。异步的话,5s等待就等待,其他事情不耽误做
|
|
哪些语句会放入异步任务队列中?
定时器
Promise
事件监听(比如click事件只有在被点击时才会触发)
观察者模式
Event loop事件循环
JavaScript只能是单线程,否则会带来很复杂的同步问题。比如,假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?
- 所有任务都在主线程上执行,形成一个执行栈。
- 主线程之外,还存在一个”任务队列”(task queue)。遇到异步代码就加入到任务队列中。
- 一旦”执行栈”中的所有同步任务执行完毕,系统就会从”任务队列”中取出需要执行的代码并放入执行栈中执行
- 主线程不断重复上面的第2,3步【执行栈中执行完成 -> 从任务队列中取 -> 执行栈中执行完成了 循环】。123456789101112131415// 执行顺序问题console.log(0);setTimeout(function () {console.log(1);},0);new Promise(function(resolve,reject){console.log(2)resolve(3)}).then(function(val){console.log(val);})console.log(4);//答案0,2,4,3,1//同步执行完 > then > 定时器
Promise的知识点
3个状态
- pending等待态: 初始状态,既不是成功,也不是失败状态。
- fulfilled完成态: 异步操作成功。
- rejected拒绝态: 异步操作失败。
2个过程
- 异步操作成功,pending -> fullfilled (执行resolve)
- 异步操作失败,pending -> rejected (执行reject)
Promise链式调用
|
|
手写实现Promise版的ajax
|
|
async/await
作用:把异步代码写成同步代码的形式
|
|
- async 表示这是一个async函数,await只能用在这个函数里面。
- await 表示在这里等待promise返回结果了,再继续执行后面的代码。
- async异步函数可以看成是generator函数的语法糖
ajax知识点
除了ajax,还能通过fetch进行通信
手写ajax
POST请求需要设置xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded')
5种readyState(请求状态)
- 0:未初始化。尚未调用open()方法
- 1:启动。已经调用open()方法,尚未调用send()方法
- 2:发送。已经调用send()方法,尚未接收到响应
- 3:接收。已经接收部分响应数据。
- 4:完成。已经接收到全部响应数据,可以在客户端使用了。
xhr.status状态码
- 2xx:请求成功
- 3xx:需要重定向,浏览器会自动跳转
- 4xx:客户端请求错误(用户发过来的地址不正确)
- 5xx:服务端错误
200:正常。
301:永久重定向,浏览器会记住
302:临时重定向
304:该资源在上次请求之后没有任何修改(可以直接使用浏览器缓存)。
400:bad request,请求存在语法错误,服务器无法识别
401:unauthorized,请求需要认证
403:forbidden,请求的资源禁止被访问。
404:需要访问的资源不存在。
405:需要访问的资源被禁止。
500:internal sever error,服务器内部错误。
502:Bad GateWay,错误网关
503:service unavailable,服务器正忙,可能服务器临时过载或停机维护。
get和post的区别
- GET 的参数放在 url 的查询参数里,POST 的参数(数据)放在请求体里。
- POST比GET安全【因为GET的参数直接暴露在url中
- GET 传送的参数有长度限制。POST 的参数(数据)没有长度限制(因为参数放在请求体里)
- GET 用来获取数据,POST 用来写数据,POST 不幂等(注册 10 个和 11 个帐号是不幂等的;对文章进行更改 10 次和 11 次是幂等的。幂等指服务器上的资源总数不变)
除了get和post,还有哪些请求方式?
GET:获取资源
POST:提交或者创建
DELETE:删除资源
PATCH:部分修改数据
PUT:整体替换资源
HEAD:获得报文首部
OPTIONS:查询相应URI支持的HTTP方法。
怎么跨域?JSONP 是什么?CORS 是什么?
ajax无法跨域
可以通过 JSONP,CORS,document.domain,postMessage,WebSocket实现跨域
同源策略
- 协议:http或https要一模一样
- 域名:网址要一模一样
- 端口:端口要一模一样【http默认端口80,https默认端口443】
jsonp
ajax不能跨域,但是script标签可以跨域~
JSONP = JSON + Padding(包裹)
原理是:动态创建script标签,并传递一个callback名(callback=abc)给服务端,然后服务端返回数据时会将这个callback名作为函数名来包裹住JSON数据,前端只需要定义好与callback名同名的函数abc,在函数内部处理参数即可
|
|
浏览器传一个callback名过去告诉服务器,本地调用的函数叫做flightHandler
于是服务端将数据包裹在这个callback名内
浏览器收到后,json数据直接以入参的方式, 放置到function中,自动执行该函数。
因为jsonp是通过动态创建<script>
标签实现的,而script只能发送GET请求,不能POST,如果想post跨域怎么办?因此又有了cors跨域
cors
jsonp只能get跨域,不能post跨域,因此需要cors
服务端设置http header实现跨域
后端程序员添加response.setHeader("Access-Control-Allow-Origin", "*");
当你使用 ajax 发送请求时,浏览器发现该请求不符合同源策略,会给该请求加一个请求头:Origin,后台进行一系列处理,如果确定接受请求则在返回结果中加入一个响应头:Access-Control-Allow-Origin; 浏览器判断该相应头中是否包含 Origin 的值,如果有则浏览器会处理响应,我们就可以拿到响应数据,如果不包含浏览器直接驳回,这时我们无法拿到响应数据。所以 CORS 的表象是让你觉得它与同源的 ajax 请求没啥区别,代码完全一样。
document.domain
v.qq.com
和www.qq.com
不同源,但是他们的二级域名都是qq.com
,如果v.qq.com
需要获取www.qq.com
的cookie,只需要设置document.domain = 'qq.com'
,即可共享cookie
postMessage
这种方式通常用于获取嵌入页面中的第三方iframe。一个页面发送消息,另一个页面判断来源并接收消息
闭包知识点【返回一个函数】
闭包的概念:「函数」和「函数内部能访问到的变量」的总和,就是一个闭包。【闭包就是能够读取其他函数内部变量的函数】
什么是闭包?
闭包的作用:「间接访问一个变量」,换句话说,「隐藏一个变量」。使得变量只在能该函数内部访问,外部无法直接访问和修改变量,从而达到收敛权限的目的
闭包缺点:对内存的消耗比较大,可能导致内存泄露
|
|
闭包的应用
|
|
this的指向
this只有在函数被执行时才能确认
箭头函数中的this是在定义函数的时候就确定了,而不是在执行函数时确定,继承自父执行上下文中的this
- 直接调用,fn()的this指向window,在严格模式下为undefined
- 对象调用,a.b.c.fn()的this指向a.b.c
- 事件调用,div.onclick = function(){/这里的this指向div/}
- 构造函数
new Fn()
的this指向新生成的实例对象 - 箭头函数的this是继承自父执行上下文中的this【它的上一级的 this】
- this指向 call,apply,bind 的第一个参数
【https://zhuanlan.zhihu.com/p/23804247】
箭头函数say,它的父级是obj,而obj在window下【window.obj】,因此这里的this.x实际上表示的是window.x,因此输出的是11。
call,apply,bind的区别
call 和 apply 都是为了解决改变 this 的指向。作用都是相同的,只是传参的方式不同。
- 除了第一个参数外,call 可以接收一个参数列表,apply 接受一个参数数组。
- bind 和call一样,接收一个参数列表,只是call直接执行函数,而bind会返回一个函数,且该函数的this绑定死了,后期无法再次改变。
|
|
在严格模式下, fn 里的 this 就是 call 的第一个参数,也就是 undefined。
在非严格模式下(不加”use strict”), call 传递的第一个参数如果是 undefined 或者 null, 那 this 会自动替换为 Window 对象
立即执行函数
作用:ES5没有块级作用域,所以只能通过 函数作用域 来防止污染全局变量
立即执行函数通过造出函数作用域,防止污染全局变量
ES6可以使用块级作用域
作用域链
- 函数在执行的过程中,先从自己内部找变量
- 如果找不到,再从创建当前函数所在的作用域去找, 以此往上,直到window
|
|
合并数组
|
|
浅拷贝
Object.assign
|
|
深拷贝
JSON.parse(JSON.stringify(obj))
|
|
缺点:不支持拷贝 函数、undefined、Symbol
递归拷贝
|
|
数组去重
|
|
原型
这种抽象的题目,通过举例子回答。
https://zhuanlan.zhihu.com/p/23090041
- var arr = [1,2,3];
- 为什么arr可以使用push()方法,这个push()方法从哪得到的?当试图得到对象的某个属性时,如果它本身没有,就会去它的proto中寻找
- arr.proto === Array.prototype 【arr是个数组,因此它的proto指向构造函数Array的原型(公共属性和方法)】
- 在Array的公共方法中,有push()这个方法
- arr就是顺着原型链调用的push()方法
|
|
编写原型/面向对象的例子
js中没有类的概念,因此面向对象是依靠原型来实现的
改写成ES6写法
原型链
当一个对象想要获取某个属性或调用某个方法,而它本身没有时,就会顺着它的proto === 它的构造函数.prototype 里找。
用instanceof判断构造函数
|
|
如何判断这个属性是否是对象本身拥有的属性?
遍历自身属性和方法
哪些方法可以创建一个对象
|
|
new做了什么?
- 创建一个空对象
- this指向这个空对象
- 这个空对象的proto指向构造函数的prototype
- 开始执行代码(即对this赋值)
- return 这个对象
如果构造函数中没有手动写return,则默认return这个对象;如果手动return的话,基础类型自动无效,比如return 123
,最终还是return这个对象;如果手动return引用类型,则返回手动写的这个引用类型
如何实现继承
ES5通过原型链
|
|
ES6通过extends继承,super导入
|
|
ES6新增的数据类型有哪些?
- Set:类似于数组,但Set中不允许出现重复的元素
- Map:类似于对象,但Map的key可以是任何数据类型
DOM押题
DOM事件机制/js事件机制/事件模型/事件流是什么?
一个事件的触发过程主要有三个阶段:捕获阶段,目标阶段,冒泡阶段
可以通过addEventerListener设置冒泡和捕获【默认false冒泡】
描述DOM事件捕获的具体流程
window -> document -> html -> body -> … -> 目标元素
补充:
通过document.body获取body标签
通过document.documentElement获取html标签
mouseover和mouseenter的区别
- mouseover:当鼠标移入元素或其子元素都会触发事件,所以有一个重复触发,冒泡的过程。对应的移除事件是mouseout
- mouseenter:不会导致冒泡,对应的移除事件是mouseleave
event对象
- event.preventDefault();
- event.stopPropagation(); //停止冒泡
- event.currentTarget 【绑定了该事件的这个对象】
- event.target 【当前被点击的元素】
querySelector与getElementBy等的区别
- 接收的参数不同,getElementBy传字符串,querySelector传css选择器
- query返回一个静态的 NodeList,而getElement这种方法返回一个动态的HTMLCollection。静态的就是说选出的所有元素的数组,不会随着文档操作而改变
移动端的触摸事件了解吗?
touchstart touchmove touchend touchcancel
模拟 swipe 事件
记录两次 touchmove 的位置差,如果后一次在前一次的右边,说明向右滑了。
事件委托/事件代理是什么?有什么好处?
优点:使代码简洁;减少浏览器的内存占用
- 假设父元素有4个儿子,我不设置4个监听器监听4个儿子,而是只设置1个监听器监听父元素,看触发事件的元素是哪个儿子,这就是事件委托。好处:省监听器。【一个爸爸有4个儿子,他们在同一个班上上课,班主任可以分别检查4个儿子的作业完成情况,也可以委托他们的爸爸检查作业,然后将结果告诉班主任】
- 可以监听还没有出生的儿子(动态生成的元素)。【如果又生了一个儿子,爸爸会连同新儿子的作业一起检查】
编写通用的事件代理代码
|
|
HTTP押题
http报文的组成部分
请求报文:
- 请求行
- 请求头
- 空行/换行
- 请求体
响应报文:
- 状态行
- 响应头
- 空行/换行
- 响应体
https与http的区别
HTTP:超文本传输协议
HTTPS = HTTP + SSL/TLS,在HTTP和TCP之间添加一个安全协议层(SSL或TSL)
默认HTTP的端口号为80,HTTPS的端口号为443
HTTP的缺点:
- HTTP在传输的过程中使用的是未加密的明文,内容可能被窃听
- 不验证通信方身份,可能遭到伪装
- 无法验证报文完整性,可能被篡改
HTTPS就是HTTP加上SSL加密+身份认证+完整性保护
https的加密过程
客户端浏览器在使用HTTPS方式与Web服务器通信时有以下几个步骤,如图所示。
- 客户端发送一个随机值1、需要的协议以及支持的加密方法
- 服务器确认双方使用的加密方法,并给出数字证书、以及一个服务器生成的随机数2。
- 客户端收到数字证书并验证是否有效,验证通过会再生成一个随机值3,并使用数字证书的公钥去加密这个随机值3,然后发送给服务端
- 服务器使用自己的私钥,将客户端发来的随机数3解密出来
- 两端根据约定的加密方式,使用前面的三个随机数,生成”对话密钥”,用来加密接下来的整个对话过程。
通过以上步骤可知,在 SSL/TLS 握手阶段,两端使用非对称加密的方式来通信,但是因为非对称加密速度慢,损耗性能大,所以在正式传输数据时,两端使用对称加密的方式通信。
对称加密与非对称加密的区别
对称加密:两边拥有相同的秘钥,两边都知道如何将密文加密解密。优点是速度很快
非对称加密:有公钥私钥之分,公钥所有人都可以知道,公钥用于数据的加密,但是将数据解密必须使用私钥解密,私钥只有分发公钥的一方才知道。特点是速度慢,CPU 开销大
http 2.0
采用二进制传输,引入多路复用,对Header 压缩,服务端push
TCP和UDP的区别
简答:TCP 可靠(能够知道发送的请求是否成功)、面向连接、相对 UDP 较慢;UDP 不可靠,不面向连接、相对 TCP 较快。 补充:
- 什么叫面向连接呢?事先为所发送的数据开辟出连接好的通道,然后再进行数据发送。【像打电话,只能两人打,第三人打就显示占线。】
- 非面向连接:是指通信双方不需要事先建立一条通信线路,而是把每个带有目的地址的包(报文分组)送到线路上,由系统自主选定路线进行传输。【就像写信,不管对方有多忙,把信放到邮筒,就与自己无关系了。】
从输入 URL 到页面展现中间发生了什么?
301和302的区别
- 301 永久重定向,浏览器会记住
- 302 临时重定向
HTTP缓存怎么做?
添加Cache-Control: max-age=300
通过修改查询参数来取消缓存
Cache-Control 和 Etag 的区别是什么?
Cookie 是什么?Session 是什么?
- cookie是存储在浏览器上的一小段「数据」,用来记录某些当页面关闭或者刷新后仍然需要记录的信息。
- session是一种让服务器能识别某个用户的「机制」。session 在实现的过程中需要使用cookie
Cookie
- 服务器响应浏览器的请求时,会种下Cookie(服务端通过在Response headers中设置set-cookie来让浏览器种下cookie)
- 浏览器每次访问指定域名时会自动带上Cookie
- Cookie 一般用来记录不敏感信息,如用户名
cookie的相关操作?
|
|
Session
当一个用户打开淘宝登录后,刷新浏览器仍然展示登录状态。服务器如何分辨这次发起请求的用户是刚才登录过的用户呢?这里就使用了session保存状态。
用户在输入用户名密码提交给服务端,服务端验证通过后会在后端创建一个session用于记录用户的相关信息的对象。
创建session后,会把关联的session_id 通过set-Cookie 添加到响应头中
浏览器在加载页面时发现响应头中有 set-cookie字段,就把这个cookie 种到浏览器。
当下次刷新页面时,发送请求会自动带上这条cookie, 服务端在接收到后根据这个session_id来识别用户。
session的使用方式:session_id存在客户端的cookie里,服务端session存用户数据;当客户端访问服务端时,自动带上cookie,根据cookie里的session_id找用户数据
- Session 数据放在服务器上
- Session 需要通过在 Cookie 里记录 SessionID 实现
- SessionID 一般是随机数
LocalStorage 和 Cookie 的区别是什么?
- Cookie 会随请求被发到服务器上【每次请求都会带上,影响获取资源的效率】,而 LocalStorage 不会
- Cookie 存储量为4kb【因为每次发送请求,都会自动带上cookie,所以cookie不能太大】,LocalStorage 一般5Mb 左右
cookie的api用起来很麻烦,不是key:value的对象形式,而是字符串”a=1; b=2; c=3”这种形式,操作起来不方便;LocalStorage是key:value的对象形式,它的api用起来方便(localStorage.getItem(key))
localStorage:永久存储,除非手动删除;
- sessionStorage:数据在当前浏览器窗口关闭后自动删除。
- cookie:数据在设置的过期时间之前一直有效(如果没有设置过期时间,则在浏览器关闭时删除)
LocalStorage 和 SessionStorage的区别
完全一样,除了【LocalStorage永久存储;SessionStorage在会话结束后清空】
Load 和 DOMContentLoaded 的区别?
页面中的 DOM,CSS,JS,图片已经全部加载完毕后才会触发Load事件。
DOMContentLoaded 事件触发代表初始的 HTML 被完全加载和解析,不需要等待 CSS,JS,图片加载完成。
Vue押题
Vue与React的区别/为什么选择Vue而不用React
- 我发现贵公司的主页用的是Vue,所以我也用Vue
- 模板 —— vue的模板基于html,react基于jsx。JSX糟糕透了,因为JSX的可读性太差,它硬是把HTML和JS混合在一起
- 开发风格:React把html和css全部写进js,即all in js;vue采用单文件组件格式,即html,css,js写在同一个文件
- React的生命周期函数太长~~~了
- Vue有指令、过滤器,比如v-model进行双向数据绑定,在React中,如果有10个input,那你就要绑定10个事件;而在Vue中,只需要v-model就可以了
- 已经熟悉Vue了,没有必要再学一个定位相似的东西,React能实现的我用Vue也能做到
Vue的生命周期钩子函数
Vue 实例从创建到销毁的过程,就是生命周期。
Vue提供的可以注册的钩子都在上图片的红色框标注。 他们分别是:
- beforeCreate:在实例初始化之后,数据观测(data observer) 和 event/watcher 事件配置之前被调用。
- created:实例创建完成之后被调用。在这一步,实例已完成以下的配置:数据观测(data observer),属性和方法的运算, watch/event 事件回调。然而,尚未挂载到DOM上,$el 还不可用。
- beforeMount:在挂载开始之前被调用:相关的 render 函数首次被调用。
- mounted:el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。如果 root 实例挂载了一个文档内元素,当 mounted 被调用时 vm.$el 也在文档内。
- beforeUpdate:数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。 你可以在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程。
- updated:由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态,因为这可能会导致更新无限循环。该钩子在服务器端渲染期间不被调用。
6.1 ativated:keep-alive 组件激活时调用
6.2 deactivated:keep-alive 组件停用时调用 - beforeDestroy:实例销毁之前调用。在这一步,实例仍然完全可用。
- destroyed:Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。 该钩子在服务器端渲染期间不被调用。
8.1 errorCaptured:当捕获一个来自子孙组件的错误时被调用。
| 钩子函数 | 描述 | 例子 |
| ——– | —— | ——— |
| beforeCreate | 实例初始化,$el 与 data 都未初始化 | 此时无法获取到this(data和methods) |
| created | 实例创建完成,data 配置完成但挂载还未开始 $el 仍未初始化 | 此时可以获取到this(data和methods),一般用于异步数据的请求/初始化(将$bus绑定到this.prototype、读取localStorage等) |
| beforeMount |挂载开始前,render 函数被调用,$el 和 data 配置完成,但数据未在 DOM 上渲染 |
| mounted | 挂载完成,el 被新创建的 vm.$el 替换并挂载到实例上去,data里的初始数据在 DOM 上渲染完毕 | 此时可以获取由data里初始数据渲染后的DOM节点;可以获取ref |
| beforeUpdate | 数据更新时调用,但不进行 DOM 重新渲染 |
| updated | 数据更新并且 DOM 重新渲染,此时可执行依赖于 DOM 的操作 | 此时可以获取到异步请求的数据替换初始数据渲染后的DOM节点 |
| beforeDertroy | 实例销毁前 |
| destroyed | 实例销毁后 |
日期new Date()
不能放在data:{time:new Date()}
,这样日期不会实时变化,可以放在created
或者mounted
这两个生命周期函数内
第一次页面加载会触发哪几个钩子?
答:会触发 下面这几个beforeCreate, created, beforeMount, mounted 。
DOM 渲染在 哪个周期中就已经完成?
答:DOM 渲染在 mounted 中就已经完成了。
updated和this.$nextTick(callback)
api:this.$nextTick(callback)
在数据改变之后立即使用this.$nextTick,待 DOM 渲染完成之后,会执行nextTick里的callback
如果在数据变化并重新渲染DOM完成之后,要操作DOM,就用this.$nextTick
如果不操作DOM,那就用watch侦听器
updated:只要data里的任何一个数据发生变化,就会触发;watch可以侦听data里具体某个数据的变化
父子组件的生命周期
父子组件的加载渲染过程,
父组件beforeCreated ->父组件created ->父组件beforeMounted ->子组件beforeCreated ->子组件created ->子组件beforeMounted ->子组件mounted -> 父组件mounted。
可以看出,父组件的mounted最后
子组件更新过程:
父beforeUpdate->子beforeUpdate->子updated->父updated
父组件更新过程:
父beforeUpdate->父updated
销毁过程:
父beforeDestroy->子beforeDestroy->子destroyed->父destroyed
继承组件的生命周期
继承组件的生命周期是交替执行的
Vue的组件通信
- 父子通信(使用 Prop 传递数据、使用 v-on 绑定自定义事件)
- 爷孙通信(通过两次父子通信,爷爷先传给爸爸,爸爸再传给儿子)
- 兄弟通信(new Vue() 作为 eventBus)
Vue-router
利用hash做前端路由,根据对应的路由渲染对应的组件,实现无刷新页面
hash虽然在URL中,但不被包括在HTTP请求中;改变hash不会重加载页面。
Vuex 的作用是什么?
Vuex是状态管理中心,它方便组件之间进行状态的传递,任何组件都能获取到vuex中的状态,并能通过触发行为来改变状态
作用:用于状态管理,相当于本地数据库,响应式地处理数据
https://vuex.vuejs.org/zh-cn/intro.html
Vuex的实现原理
Vue 的双向绑定是如何实现的?有什么缺点?
https://www.cnblogs.com/libin-1/p/6893712.html
https://segmentfault.com/a/1190000006599500#articleHeader6
view更新 -> data也更新
data更新 -> view跟着更新
view更新 -> data也更新,这个简单,可以通过事件监听即可,比如给input输入框添加onchange事件
关键点在于data更新时,如何让view跟着更新?vue.js采用Object.defineProperty()来实现数据劫持,通过Object.defineProperty()来劫持各个属性的setter,getter,
结合发布-订阅模式的方式,在数据变动时发布消息给订阅者,触发相应的监听回调(来改变视图),这样就可以实现data驱动view更新了。
当你把一个普通的 JavaScript 对象传给 Vue 实例的 data
选项,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。
对于Object.defineProperty,主要是靠将普通属性变成访问器属性。访问器属性内部拥有两个方法,getter方法与setter方法。当用户读取对象的属性时,就调用其getter方法,当用户为此属性赋值时,就会调用setter方法。
https://github.com/huangchucai/MVVM-
Computed 计算属性的用法?跟 Methods 的区别。
https://zhuanlan.zhihu.com/p/33778594
数据结构与算法押题
排序算法
二分查找法
- 先将数组从大到小排序
- 从有序数组的中间开始查找,如果正好是要找的值,就return,否则
- 如果大了,就去左半边查找;如果小了,就去右半边查找;
- 重复第1步
翻转二叉树
安全押题
XSS跨站请求攻击
向页面注入js脚本:输入框里的value不是文本,而是一段js代码,此时这段恶意js代码被执行了,就是XSS攻击
|
|
- hacker写了一篇博客,同时偷偷插入一段
<script>
- 攻击代码可以获取cookie,并发送到hacker的服务器中
- 别人看hacker的博客,就会把查看者的cookie发送到hacker的服务器
预防:
- 方法0:将cookie设置为httpOnly,让js无法操作cookie
- 方法1:不要使用innerHTML,使用textContent
- 方法2:如果一定要用innerHTML,需要进行字符过滤http://www.cnblogs.com/xianshenglu/p/8324573.html1234567function html2Text(str) {let div = document.createElement('div');div.textContent = str;return div.innerHTML;}html2Text('<p>123</p>') // <p>123</p>
或者
CSRF跨站请求伪造
Cross Site Request Forgery
用户已经登录某网站后,攻击者构造某网站后台某个功能接口的请求地址,诱导用户去点击或者用特殊方法让该请求地址自动加载(比如在img中插入该接口的请求<img src="weibo.com/add_friend">
)。
简单点说,CSRF 就是利用用户已经登录的状态发起恶意请求。
- 过程
- 用户登录新浪微博 weibo.com
- 用户切换到 hacker.com(恶意网站)
- hacker.com 发送一个 weibo.com/add_friend 请求,让当前用户关注陌生账号 。
- 用户在不知不觉中关注了很多营销号。
用户没有想发这个请求,但是 hacker 伪造了用户发请求的假象。
- 避免
- 验证 Referer:通过验证 Referer 来判断该请求是否为第三方网站发起的,weibo.com 可以拒绝来自 hacker.com 的请求
- 验证 Token :服务器下发一个随机 Token,每次发起请求时将 Token 携带上,服务器验证 Token 是否有效。
- 增加密码、短信验证码的验证
模块化押题
AMD规范
AMD是RequieJS的模块定义规范,它通过Require.js实现
AMD会异步加载(按需加载)js,依赖了什么模块就加载这个模块
CMD
CMD是SeaJS定义的模块化规范
CommonJS规范
CommonJs是nodejs的模块化规范
CommonJs不会异步加载JS,而是一次性加载出来
CommonJs可以配合npm使用
webpack基于CommonJs规范
ES6 module
在没有标准的时代,弄一些非标准的标准作为过渡
如今,已经有了标准的规范,从即刻起开始用 ES6 module
webpack押题
作用:
- 处理模块化(因为浏览器不支持module)
- 编译语法(将Less转成Css,将ES6转成ES5)
- 代码压缩
有哪些loader和plugin?
loader的规则从右往左执行
转译出的文件过大怎么办?
- 使用code split(代码拆分)实现按需异步加载模块
在vue单页应用中,若不做任何处理,所有vue文件会打包为一个js文件,这个js文件非常的大,造成网页在首次进入时比较缓慢。利用code split(代码拆分),会将代码分离到不同的js中,然后进行按需加载这些js文件,能够提高页面首次进入的速度,网站性能也能够得到提升。
|
|
- 生产环境,压缩混淆并移除console
- 通过CND从外部引入,再配置 externals, 使webpack可以处理使之不参与打包
转译速度慢什么办?
使用HappyPack 和 DllPlugin 来提升你的 Webpack 构建速度
写过 webpack loader 吗?
http://www.alloyteam.com/2016/01/webpack-loader-1/
技术选型
- 流行:目前流行的技术有哪些,能否用到我的项目中
- 团队:团队对某种技术的熟悉程度,学习成本
- 业务需求:能否套用现在的成熟解决方案/库来快速解决业务需求
- 维护成本
对前端前景的展望,前端未来会怎么发展
前端社区
掘金,segmentfault,github,官方文档,v2ex,知乎(尤雨溪也在上面)
谈谈内容,样式,行为的分离
html负责内容
css负责样式
js负责行为
为什么这三者要分离?(反过来回答:如果不分离会导致……)
如果用html负责样式
这样会使得html的标签有些是用来表示内容的,有些是用来表示样式的,导致html结构很复杂,很难区分这些标签的逻辑结构
如果用css负责内容
建议设置css,然后通过addClass和removeClass来切换样式
关于性能优化
如果在图片下载下来之前就知道img的宽高,那么就把宽高写进img标签内;否则浏览器会先用一个小宽度的占位符,等到大图下载下来后,由于宽高撑大了原本的占位符,于是之后的元素的位置要往后退,这会导致重排(reflow),重排非常的浪费性能。
异步与回调
异步
异步:不等结果,直接进行下一步
同步 vs 异步:
同步:定时器的结果出来后,才进行下一步
异步:不等定时器的结果,马上进行下一步
回调
可以通过callback回调拿到异步结果
this
this的指向
|
|
当前方法属于谁,this就是谁
箭头函数的this
|
|
箭头函数是和父级上下文绑定在一起的!!比如这里的箭头函数中的this.n,箭头函数本身与sayN平级,sayN在对象obj中,而obj的父级上下文就是window,因此这里箭头函数的this指向window
new一个实例对象,this指向这个实例对象
用new命令时,默认给构造函数的起始位置加上var this = {}
,this指向这个空对象
|
|
分析:
test1()等同于window.test1(),这个方法属于window,因此调用时,this指向window
new test1()会在构造函数内部生成var this = {}
要想最终结果是22,则改写成
定时器
|
|
由于定时器是异步的,所以优先执行同步代码,因此something是undefined