本篇分为九个模块:HTML、CSS、JS、DOM、HTTP、VUE、算法、安全、Webpack
一、HTML模块
1.你是如何理解HTML语义化的?
答:
- 举例,段落用 p,边栏用 aside,主要内容用 main 标签
最开始是 PHP 后端写 HTML,不会 CSS,于是就用 table 来布局。table 使用展示表格的。严重违反了 HTML 语义化。
后来有了专门的写 CSS 的前端,他们会使用 DIV + CSS 布局,主要是用 float 和绝对定位布局。稍微符合了 HTML 语义化。
再后来,前端专业化,知道 HTML 的各个标签的用法,于是会使用恰当的标签来展示内容,而不是傻傻的全用 div,会尽量使用 h1、ul、p、main、header 等标签
语义化的好处是已读、有利于SEO等。
- 对面试官说请看我的博客 (多写博客!)
2.meta viewport 是做什么用的,怎么写?
- 死背:
控制页面在移动端不要缩小显示。
- 侃侃而谈
一开始,所有页面都是给PC准备的,乔布斯推出 iPhone 3GS,页面是不适应手机屏幕的,所以乔布斯的工程师想了一个办法,默认把手机模拟成 980px,页面缩小。
后来,智能手机普及,这个功能在部分网站不需要了,所以我们就用 meta:vp 让手机不要缩小我的网页。
3.canvas 元素是干什么的?
- 丢项目
- 乖乖回答,根据自己的理解组织回答(面试官将投来赞赏的眼神)
- 查MDN canvas
let canvas = document.getElementById("canvas") //获取view
let ctx = canvas.getContext('2d') // 获取上下文
ctx.fillStyle = 'blue' //填充样式
ctx.fillRect(10,10,100,100) //画一个矩形
4.canvas和svg的区别
- svg绘制出来的每一个图形元素都是一个独立的DOM节点,可方便后期绑定事件或修改。而canvas输出的就是一整个画布。
- svg输出的图形是矢量的,后期可以通过修改参数来自由改变大小,而canvas输出标量画布,就像是一张图片一样的。
二、 CSS模块
1.(必考) 说说盒模型
content-box: width == 内容区宽度
border-box: width == 内容区宽度 + padding 宽度 + border 宽度
2. css reset
和 normalize.css
有什么区别?
考英文:
-
reset
: 重置,之前的样式我不要,a{color: red;}
,抛弃默认样式 -
normalize
: 让所有浏览器的标签都跟标准规定的默认样式一致,各浏览器上的标签默认样式基本统一。
3.(必考)如何居中?
- 水平居中:
内联(inline-block):爸爸身上写text-align:center
;
块级(block):margin-left: auto; margin-right: auto
; - 垂直居中:
见博客: css垂直居中
4.选择器优先级如何确定?
- 选择器越具体,优先级越高。
#xxx
大于.yyy
- 同样优先级,写在后面的覆盖前面的。
-
color: red !important;
优先级最高。
5.BFC 是什么?
BFC:Block Formatting Context,直译为“块级格式化上下文”。
是一个独立的渲染区域
-
overflow: hidden;
清除浮动 -
overflow:hidden
取消父子 margin 合并。父子margin合并
6.如何清除浮动?
-
overflow: hidden;
清除浮动(不推荐) - .clearfix清除浮动写在爸爸身上
.clearfix{
content:'';display: block; clear: both;
}
.clearfix{
zoom: 1; /* IE 兼容 */
}
7.css3的flex弹性布局的特性
参考博客:flex弹性布局
三、JS模块
1. JS有哪些数据类型?
JS有七大数据类型: String, Symbel, Number, Boolean, Undefined, Null, Object.
object 包括了数组、函数、正则、日期等对象
2. Promise 怎么使用?【必考】
.then
$.ajax().then(成功函数1,失败函数1)
链式.then
$.ajax().then(成功函数1,失败函数1).then(成功函数2,失败函数2)
- 如何自己生成Promise对象?
function xxx(){
return new Promise(function(resolve, reject){
setTimeout(()=>{
resolve() //或者reject()
}, 1000)
})
}
xxx.then(...)
3.手写一下AJAX?【必考】
let request = new XMLHttpRequest()
request.open(method, url)
request.onreadystatechange = function(){
if(request.readyState === 4){
if(request.state >= 200 && request.state < 300){
console.log('success')
}
}
}
request.send(body) //当method是get的时候,没有body
4.闭包是什么?【必考】
「函数」和「函数内部能访问到的变量」(也叫环境)的总和,就是一个闭包。
参考:https://zhuanlan.zhihu.com/p/22486908
- 为什么要函数嵌套函数?只是为了创建一个局部变量,去实现变量隐藏。
- 为什么要return函数呢?return 函数只是为了能够使用return的这个东西。
- 闭包的作用?闭包是为了隐藏变量,让变量不被篡改。
- 闭包会造成内存泄漏吗?不会。因为我们闭包的变量正是我们需要的变量,那么为什么会是要被回收的垃圾呢。出现这个说法是因为IE的内存泄漏的bug。
function (){
let n=0
return function(){
n+=1
}
}
let adder=()
adder() //n===1
adder() //n===2
console.log(n) //n is not defined
5.这段代码里面的this是什么?【必考】
- fn() 里面的 this 就是 window
- fn() 是 strict mode,this 就是 undefined
- a.b.c.fn() 里面的 this 就是 a.b.c
- new F() 里面的 this 就是新生成的实例
- () => console.log(this) 里面 this 跟外面的 this 的值一模一样
详细解析this请看:https://zhuanlan.zhihu.com/p/23804247
6.什么是立即执行函数?使用立即执行函数的目的是什么?【必考】
;(function (){
var name
}())
;(function (){
var name
})()
!!!!!!!function (){
var name
}()
~function (){
var name
}()
造出一个函数作用域,防止污染全局变量
ES 6 新语法
{
let name
}
7. async/await 语法了解吗?目的是什么?
-
await
必须接一个可以return new Promise
的函数 -
await
必须在async
内执行 - 目的: 是将异步代码写成同步代码。
function 摇色子(){
return new Promise((resolve, reject)=>{
let sino = parseInt(Math.random() * 6 +1)
setTimeout(()=>{
resolve(sino)
},3000)
})
}
async function test(){
let n =await 摇色子()
console.log(n)
}
test()
这段代码中,test函数必须等摇色子函数执行完成后,才将摇色子return的值赋给左边的n。
8.JS如何实现深拷贝?
- JSON深拷贝
let a = {....}
let b = JSON.parse( JSON.stringify( a ))
缺点:JSON 不支持函数、引用、undefined、RegExp、Date……
- 递归拷贝
function clone(object){
var object2
if(! (object instanceof Object)){
return object2
}else if(object instanceof Array){
object2 = []
}else if(object instanceof Function){
object2 = eval(object.toString())
}else if(object instanceof Object){
object2 = {}
}
//也可以把Array Function Object都当成Object来处理
for(let key in object){
object2[key] = clone( object[key] )
}
return object2
}
- 环
- RegExp、Date、Set、Symbol、WeakMap
9.如何实现数组去重?
- 计数排序的去重(只能正整数)
var a =[1,3,4,2,5,6,3,4,2,4]
var hashTab = {}
for(let i=0;i
注意,打印出来的是字符串(顺序根据数字大小排序),为了区分字符串和数字,所以只能应用在正整数。
- Set去重
var a =[1,3,4,2,5,6,3,4,2,4]
Array.from(new Set(a)) //[1,3,4,2,5,6]
- WeakMap 任意类型去重
10.如何用正则实现 string.trim() ?
function trim(string){
return string.replace(/^\s+|\s+$/g,'')
}
11.JS原型是什么?
- 举例
- var a=[1,2,3]
- 只有0,1,2,3,length四个key
- 那么为什么可以a.push(4),这个push是哪里来的?
a.__proto__ === Array.prototype
- push就是沿着
__proto__
找到的,也就是Array.prototype.push
- Array.prototype还有很多其他方法,比如pop, join, slice, splice
- Array.prototype就是a的原型(也就是
__proto__
)
参考:https://zhuanlan.zhihu.com/p/23090041
12.ES6中的class了解吗?
见博客:Class初识
13. JS如何实现继承?
- 原型链
function Animal(){
this.body = '肉体'
}
Animal.prototype.move = function(){}
function Human(name){
Animal.apply(this, arguments)
this.name = name
}
//Human.prototype.__proto__ === Animal.prototype//不合法
//用一个临时变量存储,等价于
var f = function(){}
f.prototype === Animal.prototype
Human.prototype === new f()
Human.prototype.useTools = function(){}
var frank = new Human()
- extends关键字
class Animal{
constructor(){
this.body = '肉体'
}
move(){}
}
class Human extends Animal{
constructor(name){
super()
this.name = name
}
useTools(){}
}
四. DOM模块
1.DOM事件模型是什么?
见博客:捕获冒泡
- 捕获
- 冒泡
- 如果这个元素是被点击的元素,那么不一定先捕获后冒泡,顺序是由监听顺序决定的
2. 移动端的触摸事件了解吗?
touchstart touchmove touchend touchcancel
- 模拟swipe事件:记录两次移动的位置,如果后一次在前一次的右边,那么就是向右滑动。
3. 事件委托是什么?有什么好处?
- 事件委托:通俗地来讲,就是把一个元素响应事件(click、keydown......)的函数委托到另一个元素。
假设父元素有4个儿子,我不监听4个儿子,而是监听父元素,看触发事件的元素是哪个儿子,这就是事件委托。 - 可以监听还没出生的儿子,同时也省监听器。
有bug,但是可以通过事件委托普通面试的代码
:
function listen(element, eventType, selector, fn){
element.addEventListener(eventType, (e)=>{
let el = e.target
if( el.matches(selector) ){
fn.call(el, e, el)
}
})
}
//有bug,但是可以通过事件委托普通面试的代码
工资12k的前端写的事件委托
:
function listen(element, eventType, selector, fn){
element.addEventListener(eventType, (e)=>{
let el = e.target
while(! el.matches(selector) ){
if(element === el){
el = null
break;
}
el = el.parentNode
}
el && fn.call(el, e, el)
})
return element
}
//工资12k的前端写的事件委托
五、HTTP模块
1.HTTP状态码知道哪些?
HTTP状态码共分为5种类型。
分类 | 分类描述 |
---|---|
1** | 信息,服务器收到请求,需要请求者继续执行操作 |
2** | 成功,操作被成功接收并处理 |
3** | 重定向,需要进一步的操作以完成请求 |
4** | 客户端错误,请求包含语法错误或无法完成请求 |
5** | 服务器错误,服务器在处理请求的过程中发生了错误 |
常用的状态码](https://www.runoob.com/http/http-status-codes.html)有:
状态码 | 状态码英文名称 | 中文描述 |
---|---|---|
100 | Continue | 继续。客户端继续其请求 |
200 | OK | 请求成功。一般用于GET和Post请求 |
202 | Accepted | 已接受。已经接受请求,但未处理完成 |
204 | No Content | 无内容。服务器处理成功,但未返回其内容。在未更新网页的情况下,确保浏览器仍然显示当前文档。 |
301 | Moved Permanently | 永久移动。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替。 |
404 | Not Found | 服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置"您所请求的资源无法找到"的个性页面 |
500 | Internal Server Error | 服务器内部错误,无法完成请求。 |
503 | Service Unavailable | 由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中。 |
2. 301 和 302 的区别是什么?
- 301是永久重定向,浏览器会记住
- 302是临时重定向
3.HTTP 缓存怎么做?
Cache-Control: max-age=300
-
http://cdn.com/1.js?v=1
避开缓存
4.Cache-Control 和 Etag 的区别是什么?
Cache在设定时间内,不会发起请求,Etag不管怎样都会发起请求,但是不一定会下载。
5.Cookie 是什么?Session 是什么?
- Cookie
a. HTTP响应通过 Set-Cookie 设置 Cookie
b. 浏览器访问指定域名是必须带上 Cookie 作为 Request Header
c. Cookie 一般用来记录用户信息 - Session
a.Session 是服务器端的内存(数据)
b. Session 一般通过在 Cookie 里记录 SessionID 实现
c. SessionID 一般是随机数
6. LocalStorage 和 Cookie 的区别是什么?
- Cookie会在请求时被带到服务器,而Localstorage不会
- Cookie一般是4k以下大小,而LocalStorage是5M左右
7.GET 和 POST 的区别是什么?【必考】
- 参数。GET的参数放在url的查询参数内,而POST的参数放在请求消息体里。
- 安全(扯淡)。POST比GET请求更安全。
- GET参数有长度限制(扯淡),一般是1024个字符。而POST参数没有限制(扯淡,一般是5~10MB的长度)。
- 包。GET请求只需要发一个包,而POST请求需要发两个以上的包,因为POST有请求消息体(扯淡,GET请求也可以用消息体)。
- GET是用来读数据,而POST是用来写数据,POST不幂等(幂等的意思就是不管发多少次请求,结果都一样)。
8. 怎么跨域?JSONP 是什么?CORS 是什么?postMessage 是什么?【必考】
- CORS(Cross-Origin Resource Sharing)跨域资源共享
'Access-Control-Allow-Origin': 'www.baidu.com'//或者指定域
- 通过 JSONP跨域
callback.call(undefined, {"name":"Lucia"})
- 降域:通过修改document.domain来跨子域
【前提:主域名要一致】
http://a.yilia.com 调用http://b.yilia.com
//将两个域名都降域,此时就可以相互访问了
- window.postMessage() 方法可以安全地实现跨源通信.
六、VUE模块
1. Vue 有哪些生命周期钩子函数?【必考】
文档Vue文档
beforeCreate,created,beforeMount,mounted,beforeUpdate,updated,activated,deactivated,beforeDestroy,destroyed,errorCaptrued
钩子函数的面试题可以点击查看
2. Vue 如何实现组件通信?【必考】
a. 父子通信(使用 Prop 传递数据、使用 v-on 绑定事件)
b. 爷孙通信(通过两对父子通信,爷爸之间父子通信,爸儿之间父子通信)
c. 兄弟通信(new Vue() 作为 eventBus),我自己也写了关于兄弟通信的博客。
3.Vuex 的作用是什么?
看文档:Vuex文档
我自己写的vuex博客
4. VueRouter 路由是什么?
VueRouter
-
$route
和$router
的区别是什么?
答:$route
是一个对象,储存路由的一些信息。$router
是vueRouter的实例。
5.Vue 的双向绑定是如何实现的?有什么缺点?
深入响应式原理
6. Computed 计算属性的用法?跟 Methods 的区别。
https://zhuanlan.zhihu.com/p/33778594
相同:都不能用箭头函数,会导致this的指向变化
不同点:
- computed:响应式,methods:非响应式
- 调用方式:computed和属性调用相同,比如
;methods是函数调用法,比如{{msg}}{{msg()}} - computed是带缓存的,依赖于响应式属性,只有当响应式属性变化时,才会重新计算;而methods的函数每次调用都会执行。computed比methods更加节约性能。
- computed可以只定义一个函数为只读属性,也可以设置其他函数的get/set变成可读写属性,这一点的methods做不到。
七、算法模块
- 排序算法(背诵冒泡排序、选择排序、计数排序、快速排序、插入排序、归并排序)
- 二分查找法
- 翻转二叉树
八、安全模块
1. 什么是 XSS 攻击?如何预防?
- XSS攻击是指通过网页开发留下的漏洞,将一些恶意代码用巧妙的方式注入到浏览器中,使用户加载并执行攻击者恶意制造的网页程序。
- 举例
div.innerHTML = userComment // userComment 内容是
// 恶意代码就被执行了,这就是 XSS
- 预防
- 不要使用 innerHTML,改成 innerText,script 就会被当成文本,不执行
- 如果你一样要用 innerHTML,字符过滤
a. 把<
替换成<
b. 把>
替换成>
c. 把&
替换成&
d. 把'
替换成'
e. 把"
替换成"
f. 代码div.innerHTML = userComment.replace(/>/g, '<').replace...
- 使用 CSP(Content Security Policy):内容安全策略,是一个额外的安全层,用来检测并削弱一些特定类型的攻击。
使用:Content-Security-Policy: policy
,在http头部返回。
2. 什么是 CSRF 攻击?如何预防?
- Cross-site request forgery,跨站请求伪造
- 过程
a. 用户在 qq.com 登录
b. 用户切换到 hacker.com(恶意网站)
c. hacker.com 发送一个 qq.com/add_friend 请求,让当前用户添加 hacker 为好友。
d. 用户在不知不觉中添加 hacker 为好友。
e. 用户没有想发这个请求,但是 hacker 伪造了用户发请求的假象。 - 预防
a. 检查 referer,qq.com 可以拒绝来自 hacker.com 的请求
b. csrf_token 来解决
九、Webpack模块
1. 转译出的文件过大怎么办?
- 使用code split
- 代码
import('xxx').then(xxx=>{console.log(xxx)})
- xxx模块就是按需加载的
2. 转义速度慢怎么办?
3. 写过webpack loader吗?
如何开发一个webpack-loader