题目
- 考察频率指相关问题的考察频率,并不是只是提到的点。
JavaScript基础
一、声明提高类问题 (考察频率:高)html
变量声明和函数声明都会提高,但函数会提高到变量前。 具体解释可参考《你不知道的JavaScript(上卷)》前端
二、js存储方式(考察频率:中)vue
- cookie
- sessionStorage
- localStorage
- indexedDB
三、什么状况下会遇到跨域,怎么解决?(考察频率:高)node
- 同源策略是浏览器的一个安全功能,不一样源的客户端脚本在没有明确受权的状况下,不能读写对方资源。若地址里面的协议、域名和端口号均相同则属于同源。
- jsonp跨域、nginx反向代理、node.js中间件代理跨域、后端设置http header、后端在服务器上设置cors。
四、Promise中的执行顺序(考察频率:高)nginx
参考阮一峰老师书中的例子es6
let promise = new Promise(function(resolve, reject) { console.log('Promise'); resolve(); }); promise.then(function() { console.log('resolved.'); }); console.log('Hi!'); // Promise // Hi! // resolved
上面代码中,Promise 新建后当即执行,因此首先输出的是Promise。而后,then方法指定的回调函数,将在当前脚本全部同步任务执行完才会执行,因此resolved最后输出。面试
五、JavaScript事件循环机制相关问题(考察频率:高)vuex
- 事件循环机制的概念
关键字:单线程非阻塞、执行栈、事件队列、宏任务(setTimeout()、setInterval())、微任务(new Promise())json
可参考: zhuanlan.zhihu.com/p/33058983segmentfault
- 宏任务、微任务、同步任务的执行顺序
setTimeout(function () { console.log(1); }); new Promise(function(resolve,reject){ console.log(2) resolve(3) }).then(function(val){ console.log(val); }) console.log(4); // 2 // 4 // 3 // 1
先按顺序执行同步任务,Promise新建后当即执行输出2,接着输出4,异步任务等同步任务执行完后执行,且同一次事件循环中,微任务永远在宏任务以前执行。这时候执行栈空了,执行事件队列,先取出微任务,输出3,最后取出一个宏任务,输出1。
六、for循环中的做用域问题(考察频率:高)
写出如下代码输出值,尝试用es5和es6的方式进行改进输出循环中的i值。
for (var i=1; i<=5; i++) { setTimeout(function timer() { console.log(i); }, i*1000); }
- 输出5个6,由于回调函数在for循环以后执行,全部函数共享一个i的引用。
- es5:
for (var i=1; i<=5; i++) { (function(j) { setTimeout(function timer() { console.log(j); }, j*1000); })(i); }
- es6:
for (let i=1; i<=5; i++) { setTimeout(function timer() { console.log(i); }, i*1000); }
七、闭包的做用(考察频率:中)
闭包的目的是外部函数能够访问内部函数的做用域(局部做用域)。好比访问到内部做用域的变量。
八、原型及原型链(考察频率:中)
参考小册《Web 前端面试指南与高频考题解析》
原型的理解
- 全部的引用类型(数组、对象、函数),都具备对象特性,便可自由扩展属性(null除外)
- 全部的引用类型(数组、对象、函数),都有一个__proto__属性,属性值是一个普通的对象
- 全部的函数,都有一个prototype属性,属性值也是一个普通的对象
- 全部的引用类型(数组、对象、函数),__proto__属性值指向它的构造函数的prototype属性值
原型链的理解
一段代码以下:
// 构造函数
function Foo(name, age) { this.name = name } Foo.prototype.alertName = function () { alert(this.name) } // 建立示例 var f = new Foo('zhangsan') f.printName = function () { console.log(this.name) } // 测试 f.printName() f.alertName() f.toString()
由于f自己没有toString(),而且f.__proto__(即Foo.prototype)中也没有toString。当试图获得一个对象的某个属性时,若是这个对象自己没有这个属性,那么会去它的__proto__(即它的构造函数的prototype)中寻找。
若是在f.__proto__中没有找到toString,那么就继续去f.__proto__.__proto__中寻找,由于f.__proto__就是一个普通的对象而已嘛!
f.__proto__即Foo.prototype,没有找到toString,继续往上找 f.__proto__.__proto__即Foo.prototype.__proto__。Foo.prototype就是一个普通的对象,所以Foo.prototype.__proto__就是Object.prototype,在这里能够找到toString。 所以f.toString最终对应到了Object.prototype.toString 这样一直往上找,你会发现是一个链式的结构,因此叫作“原型链”。若是一直找到最上层都没有找到,那么就宣告失败,返回undefined。最上层是什么 —— Object.prototype.__proto__ === null
九、重绘和回流(考察频率:中)
- 重绘:当页面中元素样式的改变并不影响它在文档流中的位置时(例如:color、background-color、visibility等),浏览器会将新样式赋予给元素并从新绘制它,这个过程称为重绘。
- 回流:当Render Tree(DOM)中部分或所有元素的尺寸、结构、或某些属性发生改变时,浏览器从新渲染部分或所有文档的过程称为回流。
- 回流要比重绘消耗性能开支更大。
- 回流必将引发重绘,重绘不必定会引发回流。
- 参考:juejin.im/post/5a9923…
十、实现一个深拷贝(思路)(考察频率:中)
对象中可能又存在对象,因此须要深拷贝。首先须要知道这是一个递归调用,而后要判断一些特殊类型(数组,正则对象,函数)进行具体的操做,能够经过Object.prototype.toString.call(obj)进行判断。
十一、js浮点数运算精度问题(0.1+0.2!==0.3)
好比在 JavaScript 中计算 0.1 + 0.2时,到底发生了什么呢?
首先,十进制的0.1和0.2都会被转换成二进制,但因为浮点数用二进制表达时是无穷的,例如。
JavaScript 代码:
0.1 -> 0.0001100110011001...(无限)
0.2 -> 0.0011001100110011...(无限)
IEEE 754 标准的 64 位双精度浮点数的小数部分最多支持 53 位二进制位,因此二者相加以后获得二进制为:
JavaScript 代码: 0.0100110011001100110011001100110011001100110011001100
因浮点数小数位的限制而截断的二进制数字,再转换为十进制,就成了 0.30000000000000004。因此在进行算术计算时会产生偏差。
参考:blog.csdn.net/helloxiaoli…
浏览器相关
十二、浏览器从加载到渲染的过程,好比输入一个网址到显示页面的过程。 (考察频率:高)
加载过程:
- 浏览器根据 DNS 服务器解析获得域名的 IP 地址
- 向这个 IP 的机器发送 HTTP 请求
- 服务器收到、处理并返回 HTTP 请求
- 浏览器获得返回内容
渲染过程:
- 根据 HTML 结构生成 DOM 树
- 根据 CSS 生成 CSSOM
- 将 DOM 和 CSSOM 整合造成 RenderTree
- 根据 RenderTree 开始渲染和展现
- 遇到<script>时,会执行并阻塞渲染
1三、浏览器缓存机制(策略)(考察频率:中)
1四、性能优化(考察频率:中)
参考小册《Web 前端面试指南与高频考题解析》
优化的方向有两个:
- 减小页面体积,提高网络加载
- 优化页面渲染
减小页面体积,提高网络加载
- 静态资源的压缩合并(JS 代码压缩合并、CSS 代码压缩合并、雪碧图)
- 静态资源缓存(资源名称加 MD5 戳)
- 使用 CDN 让资源加载更快
优化页面渲染
- CSS 放前面,JS 放后面
- 懒加载(图片懒加载、下拉加载更多)
- 减小DOM 查询,对 DOM 查询作缓存
- 减小DOM 操做,多个操做尽可能合并在一块儿执行(DocumentFragment)
- 事件节流
- 尽早执行操做(DOMContentLoaded)
- 使用 SSR 后端渲染,数据直接输出到 HTML 中,减小浏览器使用 JS - 模板渲染页面 HTML 的时间
Vue
1五、组件通讯方式 (考察频率:高)
1)父->子
-
props(v-bind)
-
$refs
2)子->父
-
events(v-on)
-
$parent $root
3)非父子组件
-
event bus
-
vuex
1六、双向绑定原理(考察频率:高)
网上各类文章不少,原理能够讲浅也能够讲深,看面试官本身的了解程度和他想考察的深度。 最基本的要讲清楚数据劫持Object.defineProperty(), 讲清楚依赖收集(Watcher、Dep)。
1七、路由导航钩子(导航守卫)(考察频率:中)
- 全局钩子
- 路由独享钩子
- 组件内钩子
看文档:router.vuejs.org/zh-cn/advan…
1八、v-if和v-show的共同点和区别(考察频率:中)
参考官方文档
都是用来作条件渲染,经过条件控制元素的显示与隐藏。
v-if 是“真正”的条件渲染,由于它会确保在切换过程当中条件块内的事件监听器和子组件适当地被销毁和重建。
v-if 也是惰性的:若是在初始渲染时条件为假,则什么也不作——直到条件第一次变为真时,才会开始渲染条件块。
相比之下,v-show 就简单得多——无论初始条件是什么,元素老是会被渲染,而且只是简单地基于 CSS 进行切换。
通常来讲,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。所以,若是须要很是频繁地切换,则使用 v-show 较好;若是在运行时条件不多改变,则使用 v-if 较好。