01 前言
工作了这么久,一直没有自己的一个技术知识沉淀,这一次去找了很多前端面试题,再加上自己的工作经验,进行一次汇总,强烈要求自己掌握以下内容,不仅要知其然,还要知其所以然。让自己以后在面试或者工作中做到“心中有佛,不虚场合”。
02 目录
下面是这篇文章的目录结构,一般比较简单的问题我就一笔带过了,主要是分享一下比较有难度的知识点,答案来自网上,如果有版权问题我会删除。还有本文只是给出一个大概的知识点,如果想要深入学习还要靠自己去查一下哦!
如果答案有错误,欢迎指正!
计算机基础
前端基础(HTML/CSS)
JavaScript
前端框架
浏览器渲染
计算机网络
手写代码
Webpack
Node
ES6
03 计算机基础
进程与线程的区别
进程是系统进行资源分配和调度的一个独立单位,线程是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位,一个进程至少有一个线程组成。
线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。
进程间通信方式
管道通信
消息队列通信
信号量通信
共享内存通信
套接字通信
函数库与系统库
系统库调用运行在内核模式,函数库运行在用户模式
系统调用是os提供的服务,处于内核态且不能直接调用,而要使用类似int 0x80的软中断陷入内核
库函数中有很大部分是对系统调用的封装
函数库属于过程调用,开销小;系统库需用户空间和内核上下文环境切换,开销大
用户态可以调用系统提供API接口调用内核来切换成内核态(中断方式)
二叉树
二叉树每一个节点不能多于两个孩子。
没有孩子的节点就是叶子节点。
一个节点有左右两个指针,若无则指向null。深度为h的二叉树最多有2^h-1个结点(h>=1),最少有h个结点。
二叉树的遍历三种方式,如下:
(1)前序遍历(DLR),首先访问根结点,然后遍历左子树,最后遍历右子树。简记根-左-右。
(2)中序遍历(LDR),首先遍历左子树,然后访问根结点,最后遍历右子树。简记左-根-右。
(3)后序遍历(LRD),首先遍历左子树,然后遍历右子树,最后访问根结点。简记左-右-根
数据库索引
索引是一种数据结构(B+树)
不推荐使用索引
(1)表记录太少;
(2)数据重复且分布平均的字段(只有很少数据值的列);
(3)经常插入、删除、修改的表要减少索引;
使用索引
(1)主键,unique字段;
(2)和其他表做连接的字段需要加索引;
(3)在where里使用>,≥,=,<,≤,is null和between等字段;
(4)使用不以通配符开始的like,where object like 'Math%';
(5)order by和group by字段;
数据库引擎
InnoDB存储引擎
MyISAM存储引擎
MEMORY存储引擎
Archive存储引擎
虚拟内存及缓冲区溢出
虚拟内存
虚拟内存是计算机系统内存管理的一种技术。
应用程序认为它拥有连续的可用的内存,实际分隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上。
虚拟内存技术可以通过覆盖或者把处于不活动状态的程序以及它们的数据全部交换到磁盘上等方式来实现。
缓冲区溢出
计算机向缓冲区填充数据时超出了缓冲区本身的容量,覆盖合法数据
危害
堆栈溢出,可以改变返回程序地址
程序崩溃,拒绝服务
执行非法代码,获取非法权限
程序运行失败,系统宕机,重启
排序算法
快速排序(nlogn)
选择排序(n^2)
插入排序(n^2)
希尔排序(n^1.5)
归并排序(nlogn)
冒泡排序(n^2)
常用git指令
下载一个项目和它的整个代码历史 git clone [url]
添加指定目录到暂存区,包括子目录 git add [dir]
提交暂存区到仓库区 git commit -m [修改信息]
同步到远程仓库, git push
列出所有本地分支 git branch
新建一个分支,并切换到该分支 git checkout -b [branch]
路由器与交换机
路由器可以给你的局域网自动分配IP,交换机只是用来分配网络数据的 路由器在网络层,路由器根据IP地址寻址,路由器可以处理TCP/IP协议,交换机不可以交换机在中继层,交换机根据MAC地址寻址,路由器提供防火墙的服务,交换机不能提供该功能。
04 前端基础(HTML/CSS)
flex容器布局
主轴属性
flex-direction
flex-wrap
flex-flow
justify-content
align-items
align-content
交叉轴属性
order
flex-grow
flex-shrink
flex-basis
flex
align-self
BFC/IFC
BFC(Block Formatting Context)叫做“块级格式化上下文"
(1)内部的盒子会在垂直方向,一个个地放置;
(2)盒子垂直方向的距离由margin决定,属于同一个BFC的两个相邻Box的上下margin会发生重叠;
(3)每个元素的左边,与包含的盒子的左边相接触,即使存在浮动也是如此;
(4)BFC的区域不会与float重叠;
(5)BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素,反之也如此;
(6)计算BFC的高度时,浮动元素也参与计算。
触发条件
(1)float的属性不为none;
(2)position为absolute或fixed;
(3)display为inline-block,table-cell,table-caption,flex;
(4)overflow不为visible
IFC(inline Formatting Context)叫做“行级格式化上下”
(1)内部的盒子会在水平方向,一个个地放置;
(2)IFC的高度,由里面最高盒子的高度决定;
(3)当一行不够放置的时候会自动切换到下一行;
CSS3的filter属性详解
blur
brightness
contrast
grayscale
hue-rotate
invert
opacity
saturate
sepia
CSS的继承属性(部分)
font-size:设置字体的尺寸
text-indent:文本缩进
text-align:文本水平对齐
text-shadow:设置文本阴影
line-height:行高
元素可见性:visibility
光标属性:cursor
CSS盒模型
W3C 标准盒模型:
属性width,height只包含内容content,不包含border和padding
IE 盒模型:
属性width,height包含border和padding,指的是content+padding+border
content-box(标准盒模型)
border-box(IE盒模型)
CSS的四种定位
Static:这个是元素的默认定位方式,元素出现在正常的文档流中,会占用页面空间。
Relative:相对定位方式,相对于其父级元素(无论父级元素此时为何种定位方式)进行定位,准确地说是相对于其父级元素所剩余的未被占用的空间进行定位(在父元素由多个相对定位的子元素时可以看出),且会占用该元素在文档中初始的页面空间,即在使用top,bottom,left,right进行移动位置之后依旧不会改变其所占用空间的位置。可以使用z-index进行在z轴方向上的移动。
Absolute:绝对定位方式,脱离文档流,不会占用页面空间。以最近的不是static定位的父级元素作为参考进行定位,如果其所有的父级元素都是static定位,那么此元素最终则是以当前窗口作为参考进行定位。可以使用top,bottom,left,right进行位置移动,亦可使用z-index在z轴上面进行移动。当元素为此定位时,如果该元素为内联元素,则会变为块级元素,即可以直接设置其宽和高的值;如果该元素为块级元素,则其宽度会由初始的100%变为auto。注意:当元素设置为绝对定位时,在没有指定top,bottom,left,right的值时,他们的值并不是0,这几个值是有默认值的,默认值就是该元素设置为绝对定位前所处的正常文档流中的位置。
Fixed:绝对定位方式,直接以浏览器窗口作为参考进行定位。其它特性同absolute定位。当父元素使用了transform的时候,会以父元素定位
CSS权重计算
第一等级:代表内联样式,如style="",权值为 1000
第二等级:代表id选择器,如#content,权值为100
第三等级:代表类,伪类和属性选择器,如.content,权值为10
第四等级:代表标签选择器和伪元素选择器,如div p,权值为1
注意:通用选择器(*),子选择器(>),和相邻同胞选择器(+)并不在这个等级中,所以他们的权值为0
CSS优化技巧
合理使用选择器
减少DOM操作,减少重绘和重排
去除无效的选择器
文件压缩
异步加载文件
减少@import的使用
px/em/rem/vh/vw
px像素(Pixel)。相对长度单位。像素px是相对于显示器屏幕分辨率而言的
em是相对长度单位。相对于当前父元素的字体尺寸。如未设置,则相对于浏览器的默认字体尺寸
rem是CSS3新增的一个相对单位。使用rem为元素设定字体大小时,仍然是相对大小,但相对的只是HTML根元素
css3新单位vw,view width的简写,是指可视窗口的宽度。假如宽度是1200px的话。那10vw就是120px。
css3新单位vh,view height的简写,是指可视窗口的高度。假如高度是1200px的话。那10vh就是120px。
05 JavaScript
闭包以及作用域
作用域是可访问变量的集合,可以分为全局作用域和局部作用域。
闭包就是将函数内部和函数外部连接起来的一座桥梁。
this是在函数运行时,在函数体内部自动生成的一个对象,只能在函数体内部使用。
事件循环机制
宏任务与微任务的区别
Node中的事件循环机制
JS垃圾回收与V8垃圾回收
JS:标记清楚法/引用计数法
V8:标记清除发/标记压缩法/增量标记法/压缩算法
原型与原型链
所有原型链的终点都是 Object 函数的 prototype 属性。
每一个构造函数都拥有一个 prototype 属性,此属性指向一个对象,也就是原型对象。
原型对象默认拥有一个 constructor 属性,指向指向它的那个构造函数。
每个对象都拥有一个隐藏的属性 __ proto __,指向它的原型对象。
JavaScript基本类型及其判断
boolean
string
number
null
undefined
symbol
object
function getType(obj) {
const str = Object.prototype.toString.call(obj);
const map = {
'[object Boolean]': 'boolean',
'[object Number]': 'number',
'[object String]': 'string',
'[object Function]': 'function',
'[object Array]': 'array',
'[object Date]': 'date',
'[object RegExp]': 'regExp',
'[object Undefined]': 'undefined',
'[object Null]': 'null',
'[object Object]': 'object'
};
return map[str];
}
JavaScript数组API
push() pop()
shift() unshift()
sort() reverse()
concat() slice()
splice() join()
indexOf() lastIndexOf()
forEach() map()
filter() every()
some() reduce()
reduceRight()
JavaScript设计模式
单例模式
适配器模式
代理模式
发布-订阅模式
策略模式
迭代器模式
操作节点API总结
查找节点
document.getElementById :根据ID查找元素,大小写敏感,如果有多个结果,只返回第一个.
document.getElementsByClassName :根据类名查找元素,多个类名用空格分隔,返回一个 HTMLCollection。
document.getElementsByTagName :根据标签查找元素, * 表示查询所有标签,返回一个 HTMLCollection。
document.getElementsByName :根据元素的name属性查找,返回一个 NodeList。
document.querySelector :返回单个Node,如果匹配到多个结果,只返回第一个。
document.querySelectorAll :返回一个 NodeList。
document.forms :获取当前页面所有form,返回一个HTMLCollection ;
创建节点
createElement创建元素
createTextNode创建文本节点
cloneNode 克隆一个节点
createDocumentFragment 创建文档碎片,主要是用来存储临时节点,大量操作DOM时用它可以大大提升性能
修改节点
appendChild
insertBefore
removeChild
replaceChild
06 前端框架
快速导航
Vue与React、Angular的区别?
Vue框架
1.对于MVVM的理解
2.Vue的双向数据绑定原理是什么
3.Vue3.0的Proxy相比于defineProperty的优势
4.请详细说下你对vue生命周期的理解
5.开发中常用的指令有哪些
6.组件之间的传值通信方式有哪些
7.Vue-router的路由实现:hash模式 和 history模式
8.vue-router有哪几种导航守卫?
9.Vuex是什么?怎么用?
React框架
Vue与React、Angular的对比
Vue与React
与React相同:
都是用了Virtual DOM。
都提供了响应式和组件化的视图组件。
将注意力集中保持在核心库,而将其他功能如(路由,全局状态管理)交给其他库。
与React的区别:
组件的响应式渲染
React组件的数据状态发生变化时,它会以该组件为根,去渲染整个组件树;而Vue只去渲染需要渲染的组件。
HTML + CSS + JS 的写法
React采用JSX的语法,将HTML、 CSS和JS混写;而Vue使用的是template模板方式,完全融合了web的经典技术。
react是整体的思路的就是函数式,所以推崇纯组件,数据不可变,单向数据流。而vue是数据可变的,双向绑定,声明式的写法。
Vue与Angular
与Angular相同:
Vue早起的灵感来源于Angular,所以很多语法是类似的,如v-if和ng-if。
与Angular的区别:
与Angular1比较,Vue的性能更加优越,AngularJS依赖对数据做脏检查,所以Watcher越多越慢;Angular的watcher会触发更一个更新,使得 “脏检查循环” 可能会运行多次。
Angular必须采用Typerscript开发,Vue刚刚才开始支持Typerscript,Vue源码已经用Typerscript重写了。
Vue的体积更小,同样使用了各自的cli打包生成的项目体积,Vue大概在30kb左右,而Angular在130kb左右。
Vue框架
1.对于MVVM的理解
MVVM 是 Model-View-ViewModel 的缩写
Model: 代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑。我们可以把Model称为数据层,因为它仅仅关注数据本身,不关心任何行为。
View: 用户操作界面。当ViewModel对Model进行更新的时候,会通过数据绑定更新到View。
ViewModel:业务逻辑层,是Vue的核心。View需要什么数据,ViewModel就要提供这个数据;View有某些操作,ViewModel就要响应这些操作。
总结:MVVM模式简化了界面与业务的依赖,解决了数据频繁更新。MVVM 充分利用双向绑定原理,使得 Model 变化时,ViewModel 会自动更新,而 ViewModel 变化时,View 也会自动变化,反之亦然。
- vue的双向数据绑定原理
监听器 Observer:用来劫持并通过Object.defineProperty监听所有属性(转变成setter/getter形式),如果属性发生变化,就通知订阅者。
订阅器 Dep:用来收集订阅者,对监听器 Observer 和 订阅者 Watcher 进行统一管理。
订阅者 Watcher:监听器Observer和解析器Compile之间通信的桥梁;如果收到属性的变化通知,就会执行相应的方法,从而更新视图。
解析器 Compile:可以解析每个节点的相关指令,对模板数据和订阅器进行初始化。
主要做的事情是:
在自身实例化时往属性订阅器(dep)里面添加自己。
自身有一个update()方法。
待属性变动dep.notice()通知时,能调用自身的update()方法,并触发解析器(Compile)中绑定的回调。
总结:vue.js 是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
Object.defineproperty方法的解释: 作用:会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。。 用法:Object.defineproperty(参数1,参数2,参数3) 返回值为该对象obj 其中参数1为要定义属性的对象(obj),参数2为要定义或修改的对象的属性名,参数3为要定义或修改的属性描述符,属性描述符是一个对象,主要有两种形式:数据描述符和存取描述符。这两种对象只能选择一种使用,不能混合使用。两者共同的属性:configurable和enumerable。数据描述符有value和writable; 而get和set属于存取描述符对象的属性。
拥有布尔值的键 configurable、enumerable 和 writable 的默认值都是 false。
属性值和函数的键 value、get 和 set 字段的默认值为 undefined。
- Vue3.0的Proxy相比于defineProperty的优势
Object.defineProperty() 的问题主要有三个:
不能监听数组的变化
必须遍历对象的每个属性
必须深层遍历嵌套的对象
Proxy 在 ES2015 规范中被正式加入,它有以下几个特点:
针对对象: 针对整个对象,而不是对象的某个属性,所以也就不需要对 keys 进行遍历。这解决了上述 Object.defineProperty() 第二个问题。
支持数组: Proxy 不需要对数组的方法进行重载,省去了众多 hack,减少代码量等于减少了维护成本,而且标准的就是最好的。除了上述两点之外,Proxy 还拥有以下优势:
Proxy 的第二个参数可以有 13 种拦截方法,这比起 Object.defineProperty() 要更加丰富
Proxy 作为新标准受到浏览器厂商的重点关注和性能优化,相比之下 Object.defineProperty() 是一个已有的老方法。
Proxy 对象用于定义基本操作的自定义行为(如属性查找,赋值,枚举,函数调用等)。let p = new Proxy(target, handler); target:用Proxy包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。 handler:一个对象,其属性是当执行一个操作时定义代理的行为的函数。
Proxy.revocable()创建一个可撤销的Proxy对象。
更多解释请看 Proxy
- 请详细说下你对vue生命周期的理解 创建阶段
创建new Vue()实例
初始化阶段
beforeCreate (创建前)vue实例的挂载元素$el和数据对象 data都是undefined, 还未初始化。
延伸: 因为在vue 初始化阶段, 这个时候data 中的变量还没有挂载到this 上, 这个时候访问值会是 undefined。beforeCreate 这个钩子在平时业务开发中比较少用。像插件内部install 方法通过Vue.use 方法安装时一般会选在beforeCreate 这个钩子内执行, vue-router 和 vuex 就是这么干的。
created (创建后) 完成了data数据、method初始化, el还未初始化。
延伸: 如果要在created阶段中进行dom操作,就要将操作都放在 Vue.nextTick() 的回调函数中,因为created() 钩子函数执行的时候 DOM 其实并未进行任何渲染,而此时进行 DOM 操作无异于徒劳,所以此处一定要将 DOM 操作的 js 代码放进 Vue.nextTick() 的回调函数中。一般我们最好不要在created里操作dom。
渲染阶段
beforeMount (载入前) vue实例的$el和data都初始化了, 相关的render函数首次被调用。实例已完成以下的配置:编译模板,把data里面的数据和模板生成html。注意此时还没有挂载html到页面上,此时,页面还是旧的。
mounted (载入后) 在el 被新创建的 vm.$el替换,并挂载到实例上去之后调用。 实例已完成以下的配置:用上面编译好的html内容替换el属性指向的DOM对象。完成模板中的html渲染到html页面中。此过程中进行ajax交互。
运行阶段
beforeUpdate (更新前) 这个生命周期里,页面中显示的数据还是旧的,但是咱们data的数据是最新的,页面尚未和最新的数据保持同步。可以在该钩子中进一步地更改状态,不会触发附加的重渲染过程。
updated(更新后)在由于数据更改导致的虚拟DOM重新渲染和打补丁之后调用。调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作。然而在大多数情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环。该钩子在服务器端渲染期间不被调用。
销毁阶段
beforeDestroy (销毁前) 在实例销毁之前调用。实例仍然完全可用。
destroyed (销毁后) 在实例销毁之后调用。调用后,所有的事件监听器会被移除,所有的子实例也会被销毁。该钩子在服务器端渲染期间不被调用。
其他生命周期
activated -
deactivated -
erroeCaptured
- 开发中常用的指令有哪些
v-model :一般用在表达输入,很轻松的实现表单控件和数据的双向绑定。
v-html: 更新元素的 innerHTML。
v-show 与 v-if: 条件渲染, 注意二者区别。使用了v-if的时候,如果值为false,那么页面将不会有这个html标签生成。则是不管值为true还是false,html元素都会存在,只是CSS中的display显示或隐藏。
v-on : click: 可以简写为@click,@绑定一个事件。如果事件触发了,就可以指定事件的处理函数。
v-for:基于源数据多次渲染元素或模板块。
v-bind: 当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM。语法:v-bind:title="msg" 简写::title="msg"
6.组件之间的传值通信方式有哪些
常见使用场景可以分为三类:
父子组件通信: props; $parent / $children; provide / inject ; ref ; $attrs / $listeners 兄弟组件通信: eventBus ; vuex 跨级通信: eventBus;Vuex;provide / inject 、$attrs / $listeners
我个人理解的可以分为两大类:
直接通信方式:props/$emit、$parent/$children、ref/$refs。
间接通信方式(需要中间人):provide/inject(爷爷传给所有子孙)、$attrs/$listeners(隔代传值)、eventBus、$emit + v-on + v-bind(通过父组件实现兄弟之间的通信)、Vuex。
7.Vue-router的路由实现:hash模式 和 history模式
hash模式 hash - 即地址栏URL中的 # 符号(此hash不是密码学里的散列运算)。比如这个URL:http://www.abc.com/#/hello, hash的值为#/hello, 它的特点在于:hash虽然出现在URL中,但不会被包括在HTTP请求中,对后端完全没有影响,因此改变hash不会重新加载页面。哈希模式也是当下单页面应用的标配,所谓前端路由的强大之处也就在这里:路由分发不需要服务器来做,前端自己就可以完成。
history模式 history - 利用了HTML5 History Interface中新增的pushState()和replaceState()方法。(需要特定浏览器支持) 这两个方法应用于浏览器的历史记录栈,在当前已有的back、forward、go的基础上,它们提供了对历史记录进行修改的功能。Vue-Router 官网里如此描述:“不过这种模式要玩好,还需要后台配置支持……所以呢,你要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。”
8.vue-router有哪几种导航守卫?
全局守卫
路由独享守卫
路由组件内的守卫
全局守卫 vue-router全局有三个守卫:router.beforeEach 全局前置守卫 进入路由之前 router.beforeResolve 全局解析守卫(2.5.0+) 在beforeRouteEnter调用之后调用 router.afterEach 全局后置钩子 进入路由之后 使用方法:
// main.js 入口文件
import router from './router'; // 引入路由
router.beforeEach((to, from, next) => {
next();
});
router.beforeResolve((to, from, next) => {
next();
});
router.afterEach((to, from) => {
console.log('afterEach 全局后置钩子');
});
路由独享守卫 如果你不想全局配置守卫的话,你可以为某些路由单独配置守卫:
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// 参数用法什么的都一样,调用顺序在全局前置守卫后面,所以不会被全局守卫覆盖
// ...
}
}
]
})
路由组件内的守卫 beforeRouteEnter 进入路由前, 在路由独享守卫后调用 不能 获取组件实例 this,组件实例还没被创建。beforeRouteUpdate (2.2) 路由复用同一个组件时, 在当前路由改变,但是该组件被复用时调用 可以访问组件实例 this。beforeRouteLeave 离开当前路由时, 导航离开该组件的对应路由时调用,可以访问组件实例 this。
9.Vuex是什么?怎么用?
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。`
Vuex有5种属性: 分别是 state、getter、mutation、action、module;
State Vuex 使用单一状态树,即每个应用将仅仅包含一个store 实例,但单一状态树和模块化并不冲突。存放的数据状态,不可以直接修改里面的数据。
Getters
Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
Mutations
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件函数:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数。Mutation 必须是同步函数。
Action
actions可以理解为通过将mutations里面处里数据的方法变成可异步的处理数据的方法,简单的说就是异步操作数据。在action里是commit mutation,这action里就是异步。在组件中使用 this.$store.dispatch('xxx') 分发 action,或者使用 mapActions 辅助函数将组件的 methods 映射为 store.dispatch 调用(需要先在根节点注入 store)。
Module
Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割。类似于命名空间,用于项目中将各个模块的状态分开定义和操作,便于维护。
辅助函数
mapState 辅助函数 当一个组件需要获取多个状态时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,我们可以使用 mapState 辅助函数帮助我们生成计算属性,让你少按几次键
mapGetters辅助函数 仅仅是将 store 中的 getter 映射到局部计算属性。
mapMutations 辅助函数 将组件中的 methods 映射为 store.commit 调用(需要在根节点注入 store)。
mapActions 辅助函数 将组件的 methods 映射为 store.dispatch 调用(需要先在根节点注入 store)。
- 其他Vue相关的问题
虚拟DOM
用 JavaScript 对象模拟真实 DOM 树,对真实 DOM 进行抽象 diff 算法 — 比较两棵虚拟 DOM 树的差异 pach 算法 — 将两个虚拟 DOM 对象的差异应用到真正的 DOM 树
vue模板解析
模板变成AST(解析器)
AST遍历静态节点(优化器)
生成渲染函数(代码生成器)
diff算法
diff算法是比对组件中的节点异同的情况
watch 与 computed 的区别
computed是计算属性,依赖其它属性值,并且 computed 的值有缓存,只有它依赖的属性值发生改变,下一次获取 computed 的值时才会重新计算 computed 的值。
watch是观察监听的作用,类似于某些数据的监听回调,每当监听的数据变化时都会执行回调进行后续操作。
当我们需要进行数值计算,并且依赖于其它数据时,应该使用 computed。当我们需要在数据变化时执行异步或开销较大的操作时,应该使用 watch
v-if 与 v-show 的区别
v-if 是真正的条件渲染,直到条件第一次变为真时,才会开始渲染 v-show是由display样式决定,不管初始条件是什么都会渲染。
v-if 适用于不需要频繁切换条件的场景;v-show 则适用于需要非常频繁切换条件的场景。
React框架
快速导航:
React
什么是React?有哪些特点?
React 中 keys 的作用是什么?
React 的生命周期?
调用 setState 之后发生了什么?
为什么虚拟 dom 会提高性能?
react diff 原理
如何更新组件的状态
其他React相关
react-redux
解释一下 Flux
Redux遵循的三个原则是什么?
列出 Redux 的组件
- 什么是React?有哪些特点?
定义:
React 是 Facebook 在 2011 年开发的前端 JavaScript 库。它遵循基于组件的方法,有助于构建可重用的UI组件。
React 是一个声明式,高效且灵活的用于构建用户界面的 JavaScript 库。(只关注View)。
由Facebook 2013.5开源,有很大的支持社区。
React的特点:
声明式设计 −React采用声明范式,可以轻松描述应用。
高效 −React通过对DOM的模拟,最大限度地减少与DOM的交互。
灵活 −React可以与已知的库或框架很好地配合。
JSX − JSX 是 JavaScript 语法的扩展。React 开发不一定使用 JSX ,但我们建议使用它。
组件 − 通过 React 构建组件,使得代码更加容易得到复用,能够很好的应用在大项目的开发中。
单向响应的数据流 − React 实现了单向响应的数据流,从而减少了重复代码,这也是它为什么比传统数据绑定更简单。
- React 中 keys 的作用是什么?
Keys 是 React 用于追踪哪些列表中元素被修改、被添加或者被移除的辅助标识。
render () {
return (
- {item}
{this.state.todoItems.map(({item, key}) => {
return
})}
)
}
1.react利用key来识别组件,它是一种身份标识,每个key对应一个组件,key 在其同级元素中具有唯一性,避免重复创建。2.key值是diff短发中对比两个虚拟DOM最重要的参考。3.React 还需要借助 Key 值来判断元素与本地状态的关联关系,因此我们绝不可忽视转换函数中 Key 的重要性。
- React 的生命周期?
初始化阶段:
getDefaultProps:获取实例的默认属性
getInitialState:获取每个实例的初始化状态
挂载阶段:
componentWillMount:组件即将被装载、渲染到页面上
render:组件在这里生成虚拟的 DOM 节点
componentDidMount:组件真正在被装载之后
更新阶段:
componentWillReceiveProps:当从父类接收到 props 并且在调用另一个渲染器之前调用。
shouldComponentUpdate:组件接受到新属性或者新状态的时候(可以返回 false,接收数据后不更新,阻止 render 调用,后面的函数不会被继续执行了)
componentWillUpdate:组件即将更新不能修改属性和状态
render:组件重新渲染
componentDidUpdate:组件已经更新
销毁阶段:
componentWillUnmount:组件即将销毁。
- 调用 setState 之后发生了什么?
在代码中调用 setState 函数之后,React 会将传入的参数对象与组件当前的状态合并,然后触发所谓的调和过程(Reconciliation)。
经过合并过程,React 会以相对高效的方式根据新的状态构建 React 元素树并且着手重新渲染整个 UI 界面。
在 React 得到元素树之后,React 会自动计算出新的树与老树的节点差异,然后根据差异对界面进行最小化重渲染。
在差异计算算法中,React 能够相对精确地知道哪些位置发生了改变以及应该如何改变,这就保证了按需更新,而不是全部重新渲染。
- 为什么虚拟 dom 会提高性能?
虚拟 dom 相当于在 js 和真实 dom 中间加了一个缓存,利用 dom diff 算法避免了没有必要的 dom 操作,从而提高性能。
用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文档当中当状态变更的时候,重新构造一棵新的对象树。
然后用新的树和旧的树进行比较,记录两棵树差异,把记录的差异应用所构建的真正的 DOM 树上,视图就更新了。
- react diff 原理
把树形结构按照层级分解,只比较同级元素。
给列表结构的每个单元添加唯一的 key 属性,方便比较。
React 只会匹配相同 class 的 component(这里面的 class 指的是组件的名字)
合并操作,调用 component 的 setState 方法的时候, React 将其标记为 dirty.到每一个事件循环结束, React 检查所有标记 dirty 的 component 重新绘制。
选择性子树渲染。开发人员可以重写 shouldComponentUpdate 提高 diff 的性能。
- 如何更新组件的状态
如何更新组件的状态?可以用 this.setState()更新组件的状态。
class MyComponent extends React.Component {
constructor() {
super();
this.state = {
name: 'Maxx',
id: '101'
}
}
render()
{
setTimeout(()=>{this.setState({name:'Jaeha', id:'222'})},2000)
return (
Hello {this.state.name}
Your Id is {this.state.id}
);
}
}
ReactDOM.render(
, document.getElementById('content')
);
其他React相关
- (在构造函数中)调用 super(props) 的目的是什么
在 super() 被调用之前,子类是不能使用 this 的,在 ES5 中,子类必须在 constructor 中调用 super()。传递 props 给 super() 的原因则是便于(在子类中)能在 constructor 访问 this.props
- React 中有哪些构建组件的方式?
函数
class类
有什么区别?
函数组件看似只是一个返回值是DOM结构的函数,其实它的背后是无状态组件的思想。
函数组件中,你无法使用State,也无法使用组件的生命周期方法,这就决定了函数组件都是展示性组件,接收Props,渲染DOM,而不关注其他逻辑。
函数组件中没有this。
函数组件更容易理解。当你看到一个函数组件时,你就知道它的功能只是接收属性,渲染页面,它不执行与UI无关的逻辑处理,它只是一个纯函数。而不用在意它返回的DOM结构有多复杂。
React-Redux
- 解释一下 Flux
Flux 是一种强制单向数据流的架构模式。它控制派生数据,并使用具有所有数据权限的中心 store 实现多个组件之间的通信。整个应用中的数据更新必须只能在此处进行。Flux 为应用提供稳定性并减少运行时的错误。
- Redux遵循的三个原则是什么?
单一事实来源:Redux 使用 “Store” 将程序的整个状态存储在同一个地方。因此所有组件的状态都存储在 Store 中,并且它们从 Store 本身接收更新。单一状态树可以更容易地跟踪随时间的变化,并调试或检查程序。
状态是只读的:改变状态的唯一方法是去触发一个动作。动作是描述变化的普通 JS 对象。就像 state 是数据的最小表示一样,该操作是对数据更改的最小表示。
使用纯函数进行更改:为了指定状态树如何通过操作进行转换,你需要纯函数。纯函数是那些返回值仅取决于其参数值的函数。
- 列出 Redux 的组件
Redux 由以下组件组成:
Action – 这是一个用来描述发生了什么事情的对象。
Reducer – 这是一个确定状态将如何变化的地方。Reducers 是纯函数,它规定应用程序的状态怎样因响应 ACTION 而改变。Reducers 通过接受先前的状态和 action 来工作,然后它返回一个新的状态。它根据操作的类型确定需要执行哪种更新,然后返回新的值。如果不需要完成任务,它会返回原来的状态。
Store – 整个程序的状态/对象树保存在Store中。
View – 只显示 Store 提供的数据。
07 浏览器渲染
输入网址到现实的过程
重定向
查看缓存
DNS解析,获取IP地址
TCP连接建立
发送报文请求
响应报文数据
浏览器解析数据
渲染
补充:这里值得注意的是,很多同学都会忽略重定向这个过程,其实重定向是一个很重要的部分。我们尝试使用webpagetest工具测试一下百度的网址。
第一次是输入 baidu.com后测试的效果
第二次是输入https://www.baidu.com后测试的效果,可见两次请求相差1.8s左右,这是一个很慢的过程。
防抖与节流
防抖
就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
节流
所谓节流,就是指连续触发事件但是在 n 秒中只执行一次函数。节流会稀释函数的执行频率。
浏览器缓存
缓存位置
Service Worker Menory Cache Disk Cache Push Cache
缓存策略
强缓存
Expires:Wed, 22 Oct 2018 08:41:00 GMT Cache-control:Cache-control: max-age=30
协商缓存
Last-Modified
If-Modified-Since
ETag
If-None-Match
BOM对象模型
screen
window
navigator
location
document
history
Location对象属性
hash 设置或返回从#开始的URL
host 设置或返回主机名和当前URL的端口号
hostname 设置或返回当前URL的主机名
href 设置或返回完整的URL
pathname 设置或返回当前URL的路径部分
port 设置或返回当前URL的端口号
search 设置或返回从?开始的URL(查询部分)
跨域相关问题
JSONP
CORS
document.domain
postMessage
nginx
window.name
cookie与session
cookie保存在客户端(浏览器);session保存在服务端(redis)
Session是由应用服务器维持的一个服务器端的存储空间,用户在连接服务器时,会由服务器生成一个唯一的SessionID,用该SessionID 为标识符来存取服务器端的Session存储空间。
例子:
当客户端第一次请求登录服务器的时候,服务器随机下发一个字符串sessionId给浏览器,以cookie的形式保存在客户端。当下次登录的时候会带上这个cookie,从而识别你是谁。
cookie的优点:
1.极高的扩展性和可用性。
2.通过良好的编程,控制保存在cookie中的session对象的大小。
3.通过加密和安全传输技术(SSL),减少cookie被破解的可能性。
4.只在cookie中存放不敏感数据,即使被盗也不会有重大损失。
5.控制cookie的生命期,使之不会永远有效。偷盗者很可能拿到一个过期的cookie。
cookie的缺点:
1.cookie数量和长度的限制。每个domain最多只能有20条cookie,每个cookie长度不能超过4KB,否则会被截掉。
2.安全性问题。如果cookie被人拦截了,那人就可以取得所有的session信息。即使加密也与事无补,因为拦截者并不需要知道cookie的意义,他只要原样转发cookie就可以达到目的了。
3.有些状态不可能保存在客户端。例如,为了防止重复提交表单,我们需要在服务器端保存一个计数器。如果我们把这个计数器保存在客户端,那么它起不到任何作用。
浏览器存储
特性 cookie localStorage sessionStorage indexDB
数据生命周期 一般由服务器生成,可以设置过期时间 除非被清理,否则一直存在 页面关闭就清理 除非被清理,否则一直存在
数据存储大小 4K 5M 5M 无限
与服务端通信 每次都会携带在 header中,对于请求性能影响 不参与 不参与 不参与
08 计算机网络
TCP/UDP协议
TCP是一种面向来连接的、可靠的、基于字节流的传输层通信协议。在计算机网络的OSI模型中,它完成第四层传输层所指定的功能。
面向连接
仅支持单播传输
面向字节流
可靠传输
提供全双工通信
UDP是一种简单的面向数据报、面向无连接、不可靠的通信协议,位于OSI模型的传输层。在网络中它与TCP协议一样用于处理数据包,是一种无连接的协议。
面向无连接
不可靠传输
提供单播、多播和广播
面向报文
TCP如何保证数据传输
检验
序列号/确认应答
超时重传
最大消息长度
滑动窗口控制
拥塞控制
GET/POST的本质区别
GET/POST的最大区别是GET请求有幂等性,但是POST请求没有。什么是幂等性呢?我们知道使用GET方法请求同样的接口,返回来的数据是不会改变的,但是对于POST请求,实现一些增删改查的操作的时候可能会发生重复提交的问题。
也就是说我们如果使用GET请求做增删改查的时候,遇到网络不好可能会多次操作,造成数据库的混乱,这是一个很严重的问题,但是使用POST就不会有这种情况。
http与https的区别
https握手
首先客户端发起请求到服务端,服务端处理后发送一个公钥给客户端。
客户端进行验证公钥,看公钥是否有效和是否过期。
客户端验证通过会产生随机值key,然后用公钥进行加密回传给服务端 服务端用私钥解密后获得客户端的随机值key。利用随机值key加密数据后传输给客户端。
客户端利用key值进行解密数据,客户端获取真正的数据
CDN的优化原理
CDN的全称是(Content Delivery Network),即内容分发网络。其目的是通过在现有的Internet中增加一层新的CACHE(缓存)层,将网站的内容发布到最接近用户的网络”边缘“的节点,使用户可以就近取得所需的内容,提高用户访问网站的响应速度。
CDN的工作原理就是将您源站的资源缓存到位于全球各地的CDN节点上,用户请求资源时,就近返回节点上缓存的资源,而不需要每个用户的请求都回您的源站获取,避免网络拥塞、缓解源站压力,保证用户访问资源的速度和体验。
HTTP 2.0 的新特性
二进制分帧
多路复用
首部压缩
流量控制
请求优先级
服务器推送
常见HTTP首部
通用首部
Cache-Control: 控制缓存的行为
Connection:逐跳首部,连接的管理
Date:创建报文的日期时间
Pragma:报文指令
Trailer:报文末端的首部一览
Transfer-Encoding:指定报文主体的传输编码方式
Upgrade:升级为其他协议
请求首部
Accept: 用户代理可处理的媒体类型
Accept-Charset: 优先的字符集
Accept-Encoding: 优先的内容编码
Accept-Language: 优先的语言
Authorization: web 认证信息
From: 用户的电子邮箱地址
Host: 请求资源所在服务器
if-Match: 比较实体标记
if-Modified-Since: 比较资源的更新时间
if-None-Match: 比较实体标记(与if-Match相反)
if-Range: 资源为更新时发送实体Byte的范围请求
if-Unmodified-Since: 比较资源的更新时间
Referer: 对请求中的 Url 的原始获取方法
User-Agent: HTTP 客户端程序的信息
响应首部
Accept-Ranges: 是否接受字节范围请求
Age: 推算资源创建经过时间
ETag: 资源的匹配信息
Location: 令客户端重定向至指定的URL
Proxy-Authenticate: 代理服务器对客户端的认证信息
Rety-After: 对再次发起请求的时机要求
Server: HTTP服务器的安装信息
Vary: 代理服务器缓存的管理信息
WWW-Authenticate: 服务器对客户端的认证信息
Web安全
浏览器安全
跨站脚本攻击(XSS)
跨站请求伪造(CSRF)
点击劫持(ClickJacking)
扫码登录实现原理
二维码与网页服务器
当我们打开微信的网页版的时候,查看控制台发现发送了一个请求登录的请求,然后网页服务器就随机产生了一个uuid返回给浏览器,而且这个uuid是和二维码绑定在一起的。服务器会把uuid作为key存进redis缓存服务器里面,类似 uuid:xxxx 的形式。
二维码与手机服务器
手机进行扫描二维码,然后手机携带uuid和用户信息向手机的服务器发送请求,手机服务器收到之后携带uuid去redis服务器查询用户,并把uuid与用户信息绑定在一起。查询用户成功之后返回一个Token给网页服务器,通过解析这个Token可以拿出用户的信息,然后浏览器就成功登录微信了。
前后端鉴权
前后之间进行数据交互,当然后端要判断你是否是真正的操作者,只有符合条件的用户才可以操作。也就是说必须要有一个身份证明你是一个好人。通常会有四种方式:
HTTP Basic Authentication
session-cookie机制
Token验证
OAuth开放授权
单点登录的实现
实现一个认证中心,登录并保存用户信息
访问A系统先定向到认证中心
访问B系统先定向到认证中心
则A/B系统就可以间接打通
HTTP请求方法
delete(删除文件)
options(询问支持方法)
trace(追踪路径)
connect(要求用隧道协议连接代理)
ajax/axios/fetch区别
ajax
不符合现在前端MVVM的浪潮
基于原生的XHR开发,XHR本身的架构不清晰
jQuery整个项目太大,单纯使用ajax却要引入整个jQuery
axios
从 node.js 创建 http 请求
支持 Promise API
客户端支持防止CSRF
提供了一些并发请求的接口
fetch
更加底层,提供的API丰富(request, response)
脱离了XHR,是ES规范里新的实现方式
fetch只对网络请求报错,对400,500都当做成功的请求,需要封装去处理
fetch默认不会带cookie,需要添加配置项
fetch没有办法原生监测请求的进度,而XHR可以
webSocket通信原理
客户端会先发送一个HTTP请求,包含一个Upgrade请求头来告诉服务端要升级为WebSocket协议。
服务器就会返回101状态码并切换为WebSocket协议建立全双工连接,后续信息将会通过这个协议进行传输。
有几个头信息需要注意一下:
Sec-WebSocket-Key:客户端随机生成的一个base64编码
Sec-WebSocket-Accept:服务端经过算法处理后回传给客户端
Connection和Upgrade字段告诉服务器,客户端发起的是WebSocket协议请求
09 手写代码
由于手写代码部分需要的篇幅比较多,我就简单列举出来需要熟悉哪一些手写的知识点,大家可以自行谷歌。
bind/call/apply(查看详情)
class与原形链实现继承(查看详情)
promise的简单版
深拷贝实现
节流与防抖函数
函数柯里化(查看详情)
new的原理实现(查看详情)
常用算法排序(快排)
常见设计模式
实现水平垂直居中
重要的是多刷题,可以看剑指offer,leetcode!
10 Webpack
webpack参考深入浅出webpack的书本内容,里面介绍非常到位,大家可以一看。
webpack作用
代码转换
文件优化
代码分割
模块合并
自动刷新
代码校验
自动发布
打包原理
(1)初始化参数:从配置文件和 Shell 语句中读取与合并参数,得出最终的参数;
(2)开始编译:用上一步得到的参数初始化 Compiler 对象,加载所有配置的插件,通过执行对象的 run 方法开始执行编译;
(3)确定入口:根据配置中的 entry 找出所有入口文件;
(4)编译模块:从入口文件出发,调用所有配置的 Loader 对模块进行翻译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理;
(5)完成模块编译:在经过第 4 步使用 Loader 翻译完所有模块后,得到了每个模块被翻译后的最终内容及它们之间的依赖关系;
(6)输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk,再将每个 Chunk 转换成一个单独的文件加入输出列表中,这是可以修改输出内容的最后机会;
(7)输出完成:在确定好输出内容后,根据配置确定输出的路径和文件名,将文件的内容写入文件系统中;
loader与plugin的区别
loader,它是一个转换器,文件内容进行翻译,,比如将es6转换为es5,单纯的文件转换过程
plugin是一个扩展器,它丰富了webpack本身,针对是loader结束后。webpack打包的整个过程,它并不直接操作文件,而是基于事件机制工作,会监听webpack打包过程中的某些节点,并且执行相对应的任务。
HappyPack的原理
webpack中最耗时的就是loader的转换过程,转换的流程很长。happypack的原理就是把这部分的任务拆解成多个子进程去并行处理,减少构建时间。
通过new HappyPack()实例化,然后把任务交由实例统一调度分配。核心调度器会将一个个任务分配给空闲的子进程。处理完毕后发送给核心调度器。
如何优化webpack配置
缩小文件查找范围
优化loader
优化resolve.modules
优化resolve.mainFields
优化resolve.alias
优化resolve.extensions
优化module.noPaese
使用DllPlugin
基础模块抽离,打包到动态链接库
需要使用模块,直接去动态链接库查找
使用HappyPack
单线程变多进程
使用ParallelUglifyPlugin
开启多进程压缩代码,并行执行
使用CDN加速
静态资源放到CDN服务器上面
Tree Shaking
剔除无用的代码
提取公共代码
防止相同资源重复加载
减少网络流量及服务器成本
使用prepack
编译代码时提前计算结果放到编译后的结果中,而不是在代码运行才求值
11 Node
Node的特点
异步IO
事件驱动
单线程
跨平台
V8垃圾回收机制
新生代:Scavenge算法
老生代:Mark-Sweep算法、Mark-Compact算法、Incremental Marking算法
PM2进程守候
内建负载均衡(使用 Node cluster 集群模块)
后台运行
0 秒停机重载,我理解大概意思是维护升级的时候不需要停机.
具有 Ubuntu 和 CentOS 的启动脚本
停止不稳定的进程(避免无限循环)
控制台检测
提供 HTTP API
远程控制和实时的接口 API ( Nodejs 模块,允许和 PM2 进程管理器交互 )
Buffer对象
Buffer是一个像Array的对象,它的元素都是16进制的两位数。是一个典型的JavaScript与C++结合的模块,设计性能的相关部分采用了C++实现,而非性能部分采用了JavaScript实现。Buffer对象可以用来操作二进制数据流。
Buffer对象的内存分配不是在V8的堆内存中的,而是由Node的C++层面实现的内存申请的
分配机制
小对象
slab 内存分配机制**。它是一种动态内存管理机制,采用的是预先申请,事后分配的方式,简单来说它就是一块申请好的固定大小的内存区域。有如下3种状态:
full:完全分配
partial:部分分配
empty:没有被分配
大对象
如果这个对象是超过了 slab 的大小,那么就不会占用slab块,直接使用C++层面分配你所需要的大小,这块空间就会被你一直占有
12 ES6
promise
在阮一峰老师的ES6入门标准中说到,所谓promise就是一个容器,里面保存着某个未来才会结束的事件(通常是是一个异步事件)。它有两个特点:
状态不受外界影响:拥有三种状态(Pending、Fullfilled、Rejected)。状态只取决于异步执行结果,其他过程无法改变这个状态。
状态改变不会再变:初始状态为Pending状态,它只可以变成Fullfill或者变成Rejected,但是一旦发生改变就不会再变。
promise可以使得异步操作的写法像同步写法一样优雅,代码可读性更高。但是缺点就是中途无法取消promise,一旦新建就会执行,假如没有设置回调函数,Promise内部如果出现错误不会反应到外部。
实例方法
then()/catch()
all()/race()
resolve()/reject()
done()/finally()
proxy
Proxy可以理解为,当你试图访问一个对象的时候必须先经过一个拦截或者代理,你才可以进行对对象的操作。这种机制的好处就是可以对外界的访问进行过滤和改写。
get(target, propKey, receiver) 拦截对象属性读取
set(target, propKey, value, receiver) 拦截对象的属性设置
has(target, propKey) 拦截propkey in proxy
deleteProperty(target, propKey) 拦截delete proxy[propKey]
ownKeys(target)
getOwnPropertyDescriptor(target, propKey) 返回对象属性的描述对象拦截
defineProperty(target, propKey, propDesc)
proventExtensions(target)
getPrototypeOf(target)
isExtensible(target)
setPrototypeOf(target, proto)
apply(target, object, args)
construct(target, args) 拦截 proxy 实例作为构造函数调用的操作
revocable(target, handler) 方法返回 一个可取消 Proxy实例
ES6的新特性
ES6新增了很多新特性,这里不可能每一个都详细讲述,面试中我遇到的有以下几个,你把它们都讲述清楚就可以过关了。
let、var、const区别
箭头函数
解构赋值
模板字符串
Set、Map数据结构
Promise对象
Proxy
class继承
class Parent {
constructor(value) {
this.val = value
}
getValue() {
console.log(this.val)
}
}
class Child extends Parent {
constructor(value) {
super(value)
this.val = value
}
}
let child = new Child(1)
child.getValue() // 1
child instanceof Parent // true
13 推荐书籍
《JavaScript高级程序设计》
《ES6标准入门》
《深入浅出NodeJS》
《深入浅出webpack》
《深入浅出vue.js》
《JavaScript设计模式与开发实践》
《图解HTTP》
《图解TCP/IP》
《剑指offer》 14 思考与感悟
写技术博客
不用自己去搭建一个博客(要是可以就更好了),选择一个平台,博客园、CSDN或者掘金都是不错的平台,然后就可以开始你的表演了。可以写一些最近的学习心得,面试技巧以及黑科技工具的使用等等。写博客的好处有很多,不仅可以锻炼的表达逻辑,还可以巩固你的知识体系。两全其美,何乐而不为?
另外就是可以多逛一下技术社区,了解前端的动态,多关注最近出了什么新技术、新框架、新八卦等等。试着去帮别人解答一些问题,别人也很愿意去听,但是不要抬杠。乐于分享的心态比技术本身更重要。
参考文章:
www.ruanyifeng.com/blog/2015/1… 常用 Git 命令清单
yq.aliyun.com/articles/63… Mysql四种常见数据库引擎
www.nowcoder.com/discuss/258… 个人秋招经验总结(前端方向)
www.jianshu.com/p/2fa559479… css四种定位
www.nowamagic.net/csszone/css… CSS选择器的权重与优先规则
www.runoob.com/w3cnote/px-… px、em、rem区别介绍
cn.vuejs.org/ vue官方文档——生命周期
zhangmingemma.github.io/2018/10/16/… vue-router实现原理
juejin.im/post/5d59f2… 30 道 Vue 面试题,内含详细讲解(涵盖入门到精通,自测 Vue 掌握程度)
blog.csdn.net/qq_30114149… cookie,session优缺点
blog.fundebug.com/2019/03/22/… 一文搞懂TCP与UDP的区别
www.imydl.com/work/4073.h… 使用 CDN 的好处和注意事项
segmentfault.com/a/119000001… Jquery ajax, Axios, Fetch区别之我见
juejin.im/post/5be406… PM2简易使用手册
http://www.inode.club/interview/vue.html 程序员成长指北
https://juejin.im/post/5e722aa851882548fe29322f 前端小时
https://segmentfault.com/a/1190000018604138?utm_source=tag-newest
https://segmentfault.com/a/1190000016885832?utm_source=tag-newest
https://www.jianshu.com/p/84ce8d9f5391
深入浅出 vue.js
深入浅出 webpack
JavaScript设计模式与开发实践
MDN
本文会持续更新下去的。
原文链接:益码凭川 https://www.jscwwd.com/article/5e732b15e4da98173dc1f6d9