问题记录/to do
- 不能连续定义并执行2个匿名函数,也就是说如下的代码是会报错的:
(function() {})()
(function() {})()
复制代码
问题记录 - 已解决
- es class部分从新学习后 - 实现下继承/静态变量等;
- webpack: 用css-loader开启css-module后,使用mini-css-extract-plugin进行css的split,结果打包出来的文件index.html在浏览器中没有c s s引入的效果?
- for of / for in - 对象的遍历方法
(function() {
var arr = [1, 2]
Array.prototype.pm = 456;
for (let i in arr) { console.log(`[${i}]: ${arr[i]}`); }
for (let v of arr ) { console.log(`${v}`); }
})()
复制代码
- 循环引用 - 模型是怎样的 图??
var a = { b: 1 };
a.b = a;
console.log(a);
复制代码
- 解决方法:咱们在深拷贝中若是碰见了循环引用而未做专门的处理,就会无限递归形成内存溢出,那么处理的思路呢?应该是:
- 利用缓存的思想,用一个数组缓存已经遍历过的引用,每次引用时只要查找缓存中是否登记过;若是已经登记过,则就不须要再递归了;
- 循环引用 屡次引用的地址归为一个便可,不须要递归挖掘:由于对于循环引用的处理就是:避免递归,只在第一次递归引用,后面就再也不递归了
感慨&顿悟
- 有时候感受,之因此能复用,就是由于有名字啊:命名其实对不少事物发展颇有帮助
关于学习方法
关于读书
- 应该要对知识点以Blog的形式进行输出,尤为是经典知识点
- 也就是反馈式学习,有没有读者没关系,必定要尽量输出
- 那些手册中能查到的,或者记忆性的,就不要复述了,API随时会变,要去深刻理解背后的设计机制,实现原理这样子的东西
- 以不变应万变,重视原理,要否则只会疲于奔命
- 关于阅读,有时候能够出小声读能够有助于咱们集中注意力,效果会好一些
关于算法
- 学习算法的本质是什么??是一种训练。
- 设计一个好的数据结构,再加一些算法,就行了
- 因此任何算法,都应先设计好数据结构(数据结构咱们能够从基础/元数据结构加工/改造/组合而来),让数据结构自己描述问题模型,而后再组合使用相应的算法或者设计更优的算法(若是写算法,连咱们要操做怎样的数据都不清楚的话,算法从何谈起);
- 好的算法和好的软件同样,是迭代而来的;
- 必定要学会思考,去分析问题+条件+目的,而后尝试给出一步接一步的方案
- 另外,不要思考不通就一会儿把答案看完,能够看一部分,提示性的,剩下的本身继续思考,最后再对比本身的方案和主流方案,有利于弥补思惟缺陷和提醒思惟定势
- 再到后面效率越高的排序,要有“辅助函数”的意识
-
递归
- 递归终止条件 - 就是在知足某一条件的状况下 再也不调用自身 而是返回一个‘正常值’(个人理解就是:可用于计算的值)
- 递归的本质是什么??就是栈,递归的过程就是入栈(父函数到子函数) -> 出栈执行(子函数返回值到父函数),每一次出栈执行,咱们都把结果用临时变量记录做为栈中下一个要出栈执行的函数的参数;
关于设计模式
订阅模式
- 事件队列,只是订阅模式的一种应用;
- 订阅的本质:就是把给定的一个回调添加到某一频道的队列中去;后面的触发以及管理,都经过该频道;
前端js手写
- 节流和防抖的应用场景区别
- 防抖和节流都是限制某一时间段代码执行的频次,可是实现原理不太同样
- 防抖,能够保证在delay内不会执行2次代码,也就是某一段时间内只执行一次,并且是最后一次的代码会被执行;节流,保证在一个时间间隔内只执行一次代码,并且是该段间隔中的第一次的代码;
-
防抖适用场景:
- 提交,只提交最后一次;
- 输入框联想,避免频繁联想,而是在停顿输入后一个delay内去请求联想;
- 例如:你正在适用掘金的编辑器,在你输入后的一个delay内,会右上角会显示自动保存为草稿,这里必然用的是防抖,不然频繁请求,会让服务器的压力很大;
-
节流适用场景:
- resize、动画、滑动条事件(me:由于是间隔执行,就能够认为是‘均匀’的,对于动画等同时强调流畅性的场景)
- 深克隆
关于原理
js原理
关于源码阅读
// 特殊值校验
// 主体程序
// 辅助函数
// 返回值
复制代码
style
CSS
- 利用了block水平元素宽度能够随父容器调节流动的特性
- 参考
- BFC特性
- 包裹浮动元素
- 解决margin叠加
- BFC启用
- overflow 设置为非visible的值
- position:absolute / fixed
- display: flow-root(支持有限)
- 建立table-cell表格相关
- column-span:all 建立多列布局
Flex
- 定义为Flex布局的元素若是不给明确尺寸,会自动伸展到和容器同一宽度
SCSS/SASS
HTTP
http 鉴权
- 401 是用户身份认证:是否为经过认证的用户
- 403 是当前用户权限认证:当前用户是否拥有某权限
缓存
- 缓存在网络结构中,是一个节点,就相似于代理那样(固然,浏览器也能够具备缓存能力,至关于给本身的通讯增设了一个缓存节点);
- 相比于代理,缓存具备将服务器端资源缓存到本身本地的能力,并经过一系列Http指令/机制(例如“新鲜度检测”)来肯定是否给客户端提供本地的缓存资源;
- 本质上是一种网络效率/资源优化机制;
- 缓存的核心:新鲜度校验;
- 新鲜度校验通常基于两种机制:
- 缓存资源的时间属性(上次修改时间等)
- Expires
- cache-control: Max-Age
- 缓存资源自己实体的属性(ETag(Entity Tag)等)
- 新鲜度校验通常发生在缓存节点和服务器节点之间,通讯使用的是http 1.0 和 http 1.1为缓存提供的一些首部属性;
- 缓存的控制:主要由服务端(开发者能够经过服务器配置文件)控制,固然浏览器也能够经过一些操做(Refresh)去发送一些带有cache-control的请求指令,另外文档自己也能够设置一些缓存指令:例如在html文档中,HTTP 2.0 提供的来分配http首部信息(可是这个方案性能和支持度都很差,不建议使用)
- 浏览器缓存:实际上是浏览器自己扮演了一个缓存节点来提供自身和服务器之间的缓存服务;
- 缓存:缓存资源 + 缓存标识
- 咱们能够将多个缓存指令配合使用
- 浏览器缓存策略:
- 强缓存
- Expires
- HTTP 1.0
- 一种兼容写法,自己是被淘汰的机制;
- 优先级低
- Cache-Control
- HTTP 1.1
- 响应头 + 请求头 均可以用
- 优先级高
- 协商缓存
- last-Modified
- 响应头: Last-Modified
- 请求头: If-Modified-Since
- 优先级低
- 弊端
- ETag
- 响应头: ETag
- 请求头: If-None-Match
- 优先级高
- 浏览器2种缓存策略比较:
- 性能:强缓存好
- 精确度: 协商缓存高
- 优先级: 协商缓存高
- 另外:强缓存由服务器经过强缓存指令对缓存进行设置,因此是一个单向的,协商缓存则是由一组:响应头指令 + 请求头指令 配合使用的;
- 关于浏览器缓存
跨域
jsonp
- jsonp的原理就是向后台经过url参数(通常约定为callback)传递一个回调函数的句柄(函数名),后台在经过请求信息(参数)计算处理后在响应中传回一个拼接的js(callback(data))
React
关于React的diff算法
- diff的概念:比对两棵树以比较有效率实现ui同步。
-
算法实现
- 原来的算法为对树(render方法会生成由React自定义数据结构(核心属性有type,props,children)的virtrualDomTree)的递归比较,一层一层比较,先比较父节点,再比较子节点。
- 在每一层中的比较中,对于当前比较节点,按类型分为:React元素或者原生DOM节点
- 对于Dom节点比较,先比较类型type:
- type不同,则直接从该节点为顶点销毁子树(并销毁其状态),而后用新生成VirtrualDomTree替换这一部分;
- 若是type一致,则比较其props/属性,只更旧树上的变化的属性;
- 对于React元素的比较:也是先比较type,
- type不一致的和Dom节点的处理同样,也是子该节点如下销毁旧树,把新树替换上去;
- type一致的,保留旧virtrualDomTree的实例,而后先把新树的props经过比对更新到旧树上,而后对新旧两个树的children列表进行比对(这里就是有无key的影响体现了,当子节点列表有差别时,会比对产生一个mutation),而后递归去render children(子节点)这一层,diff规则和上一层,同样;
- 那么,基于以上,咱们就能够理解当列表中两个元素相互交换位置时会发生什么??key在算法中发挥做用主要是当前层/节点的children若是是列表的话,须要首先对这个列表过一遍,以保证列表的增删改/次序位置/同节点属性等保持一致:
- 这个固然要分有无key的状况来讨论
- 有key的状况下,就会用key来进行当前节点惟一性的标记,在列表比对时,用key来表明节点进行children的列表比对,key相同的保持旧节点实例不变,只比对变动属性
- 无key的状况下,就是普通节点按次序比较了,例如2个节点仅仅是调换了一下位置就可能会把旧节点销毁了
- 另外关于index不适合做key的状况为何(其实key本质上是列表节点的一种身份标记,能够告诉react的diff算法,用来标志新旧两棵树上同一个列表节点,经过比对key,用key能够区分,那些是旧树就有的节点,哪些是新树新增长或者删除的节点,key相同的状况下,首先是保留旧节点实例的
- key的来源(原则:保持列表内惟一便可)
- 来自模型(通常源于数据库)的id值
- 能够用值的一部分利用hash映射算法生成,固然hash 要足够优
- 在不牵扯顺序调整的状况下,数组index也能够胜任
- 对了,说到对惟一性的标识,怎么能少了es6的symbol呢
React-router
React 小细节
- 刚用react那会儿对es6也不算熟,当时就感受,为何
<Todo onClick={(e) => onClick(e)} />
// 在不指定传参的状况 与下面语句基本相等 ??
<Todo onClick={onClick} />
复制代码
今天盯着看了会儿,这不就是一个函数表达式吗??眼拙啊css
onClick={(e) => onClick(e)}
// 等价于
onClick={function() { return onClick(e)}}
复制代码
Redux
- 关于react + redux中组件的划分:尽可能把视图和容器分开来设计组件,之间能够经过props来传递信息:
- 容器组件,凡是直接与Redux的store打交道的都是容器组件,通常都是通过HOC connect包装后的组件
- 展现组件,纯展现性的组件了,通常就是函数组件
- 在面对具体业务时,思路:
- 咱们的首要任务是根据任务模型设计state模型,就是设计reducer,最好的方法就是咱们先写一个defaultState做为默认值,也会对该view/功能对应的state又一个比较直观的认识;
- 而后思考咱们须要哪些操做(action.type),固然这些共用型的常量确定要用大写的const常量,而且在一个文件中集中配置管理
- 而后就是设计action了
- 最后把咱们的reducer 经过combineReducers来组合起来,而后交给createStore便可;
- 而后,进入咱们业务设计部分,这部分就分为容器组件和展现组件的划分了
- 考虑:数据的交互实际上是用户和view都和store进行交互,读写数据,这是设计的一个思考前提,也就是咱们要了解这一功能,数据须要从哪里来,到哪里去,触发什么;
- 话说,Redux完成一个功能所须要的模版文件太多了,并且不直观,业界有mobx这样的替代解决方案,但也有其一点点局限性,嗯嗯,给Redux作个辅助库,这一块找时间值得思考尝试下
使用
- Switch会只渲染第一个path属性和loaction匹配的
React-router 源码阅读感悟
- Just Component(一切皆组件)
- 组件封装了path和component之间的映射关系,而path,是标准URL中的一部分;
- 传递给组件的props.history.action属性,用法举例:
- 翻页动画:咱们能够根据action的值来判断是POP 或 PUSH 从而采起不通的翻页动画
Vue
关于组件化的认识(摘自Vue官网)
一个重要的事情值得注意,关注点分离不等于文件类型分离。在现代 UI
开发中,咱们已经发现相比于把代码库分离成三个大的层次并将其相互交织起来,
把它们划分为松散耦合的组件再将其组合起来更合理一些。
在一个组件里,其模板、逻辑和样式是内部耦合的,
而且把他们搭配在一块儿实际上使得组件更加内聚且更可维护。
复制代码
Vue组件
- Vue组件本质上是一个有名称的Vue实例,特色是能够经过名称进行复用
- 任何Vue应用,都有一个根实例、
H5 app
- 高清图显示方案
- 提供高清图:位图像素得和物理像素的数量一致,那么,当dp r=2时,css像素(200 * 300)的img,其实是由(400 * 600)的设备像素提供的显示的,那么,基于位图像素和物理像素数量一致才不会发生就近取色的算法(会致使模糊),因此,咱们要针对dpr = 2 && css(200 * 300)的img 提供(400*600)的高清图
- dpr的获取:
window.devicePixelRatio
复制代码
@media (-webkit-device-pixel-ratio){}
@media (-webkit-min-device-pixel-ratio){}
@media (-webkit-max-device-pixel-ratio){}
复制代码
koa中间件编写感悟
- 中间件 本质就是一个能够生成(返回)async函数的工厂
- 每一个中间件均可以拿到ctx和next由koa传入的参数,剩余的参数咱们经过工厂传入,也就是在app.use注册时传入
- 中间件要考虑next调用的时机,另外,若是要进行respoons的相关回复,咱们要考虑header和body两部分的设置
- 注意容错
- 对于某些中间件中依赖的部分非核心很是用库,咱们能够经过语义等将其看成黑盒对待,重视其输入和输出以及做用
- 核心库koa-send
- 最核心的实现就是:
ctx.body = fs.createReadStream(path)
- 当咱们须要获取file时,node提供的fs和path配合使用,威力很强
koa-views
koa-router
- Nesting routers is supported; - 支持路由嵌套
forums.use('/forums/:fid/posts', posts.routes(),posts.allowedMethods());
复制代码
工程化
webpack
- 关于module、chunk和bundle的区别
- module
- module对应的是咱们的源码文件,通常和源码文件一一对应,也是webpack的输入
- chunk
- chunk是webpack按照配置的规则对module进行拆分合并后的东西,通常和module是一对多(也能够是一对一,看具体的split设置)的关系,咱们的codeSplit规则通常就做用于module到chunk这个过程
- bundle
- bundle是webpack对chunk进行处理(编译压缩等)后输出到dist的文件(就是咱们最终打包产生的文件),通常和chunk是一一对应的关系;
- css split:在css文件比较大时,能够分离打包css,把css打包为单独的文件(能够避免将css打包到js中,增大js的体积),而后加快加载速度(css是与DOM并行加载的,js默认则是阻塞式加载)
- 任什么时候候使用第三方库时,阅读文档都是第一步骤:在提取并分离文件的extract-text-webpack-plugin主页咱们就看到提醒,webpack v4以后咱们提取分离文件应该用mini-css-extract-plugin
babel
- 在webpack中配置babel时,babel-loader会读取.babelrc配置文件
HMR
- 不使用react-hot-loader的话,咱们改变React组件内容,浏览器那边是自动刷新,而不是无刷新的HMR
fetch
- 从MDN关于Body对象的描述,咱们能够知道为何fetch在获取到数据后,中间还得有一层返回Body对象方法的then:
fetch('http://example.com/movies.json')
.then(function(response) {
// 为何后面能够接then ?
// 由于Body对象的方法(这里是response.json)返回的是一个Promise对象
return response.json();
})
.then(function(myJson) {
// 这里的then是上面response.json()返回的
console.log(myJson);
});
复制代码
优化
关于优化,能够分为用户体验优化(例如Loading和skeleton), 和性能优化,例如缩短首屏加载时间(理念通常是:经过codeSplit 和 缓存机制配合,让那些不易变更的包尽可能利用长缓存机制,减小远程资源请求次数(打包出来的index.html中的bundle.js在没有缓存的状况下,都会阻塞式地远程下载)。缩小首屏加载包的体积:压缩,路由和组件级的codeSplit,尽可能减小加载没必要要加载的代码。这些实现通常依靠在webpack中配置以及各类懒加载组件等辅助实现)html
性能优化
“咱们应该忘记忽略很小的性能优化,
能够说在97%的状况下,过早的优化是万恶之源,
而咱们应该关心对性能影响最关键的那另外3%的代码” -- 高德纳
复制代码
也就是说:不要将优化性能的精力浪费在对总体性能影响不大的代码上,而对于性能有关键影响的部分,优化并不嫌早。前端
性能优化梳理
白屏 {
loading
== 伪服务端渲染(只渲染首屏,poppeteer)
cache + splitCode:= 变化部分 + 不易变化部分(适合做为长期缓存,
通常为公共依赖之类的)
开启Http2
}
从白屏 到 FMP {
sketon(代替无心义页面)
}
从FMP到TTI(这一阶段主要是js阻塞:js体积 + js自己执行速度) {
TreeShaking
pollyfill动态加载
动态加载es6
路由级别split code:将首屏js拆解出来
}
组件加载 {
codeSplit - 主要依赖于懒加载
预加载 - 原理:hover
keep-alive:react-keep-alive
}
复制代码
加载优化
首屏加载
执行优化
场景问题解决
大数据量list渲染问题
- 分为“有分页”和“无分页”两种方案
- “有分页”:除了前端分页器实现,还有就是(移动端用的多)下拉到底部时触发请求,得到分页后的数据
- “无分页”:就须要用到“虚拟列表”的技术了
版本控制 git
- git的版本控制:本地仓库和远程仓库配合使用,并且就存储机制和内容方面,基本一致,也就是git一视同仁;
- git只制定了灵活度很高的规则,至于怎么玩,就由你们去想象了
- 分布式系统,也就是基本每个节点,均可以做为另外一个节点的服务器/代码仓库,资源/代码都是管理在每个节点上的;