left-pad实现
https://www.cnblogs.com/shengxinjing/p/5315549.html
从输入 URL 到页面加载完成的过程中都发生了什么事情
http://fex.baidu.com/blog/2014/05/what-happen/
重绘(redraw)和重排(reflow)
https://zhuanlan.zhihu.com/p/24599399
vue面试题
https://www.cnblogs.com/sichaoyun/p/8406194.html
https://segmentfault.com/a/1190000008102870
https://yuque.antfin-inc.com/junchen.yjc/quesub/avf828
number对象
https://blog.csdn.net/qq20004604/article/details/70882202#t14
前端动画
react面试题
https://segmentfault.com/a/1190000016761186
https://zhuanlan.zhihu.com/p/47760913
croppejs
https://github.com/fengyuanchen/cropperjs/tree/v2
搜索引擎的书
https://github.com/jhscpang/books
css渲染
https://yanhaijing.com/css/2014/04/04/10-influence-css-rendering-speed-method-and-suggestions/
inline-block
https://blog.csdn.net/wmaoshu/article/details/52964251
sort
http://louiszhai.github.io/2016/12/23/sort/
mobx
https://www.cnblogs.com/rubylouvre/p/6058045.html
webpack原理
https://juejin.cn/post/6844903971325214734
jsBridge
https://segmentfault.com/a/1190000010356403
前端面试题
阿里前端攻城狮们写了一份前端面试题答案
https://github.com/huruji/FE-Interview
https://github.com/qiu-deqing/FE-interview
https://github.com/markyun/My-blog/tree/master/Front-end-Developer-Questions/Questions-and-Answers
https://github.com/paddingme/Front-end-Web-Development-Interview-Question
https://github.com/markyun/My-blog/tree/master/Front-end-Developer-Questions/Question
Document错误类型
垃圾回收机制,内存溢出泄露排查
XSS SOL注入 网络劫持 控制台注入 钓鱼
SSR
原型,原型链
vue利用ES5的什么特性实现双向数据绑定
defineProperty
图谱去抖懒加载
intersectionOvserver
不能一道视口就加载,而是停留多少秒后加载
lacalStorage,sessionStrorage
内核
iframe缺点
垂直居中
clearfix
文字相关css可继承
js延迟加载
异步加载
浏览器缓存
性能优化
减少http请求
repaint reflow
设置style回导致reflow ,通过设置calss
减少DOM操作
使用json进行数据交换
SEO
WeakMap,WeakSet
对象深拷贝
二维数组平铺
jsonp
promise
bind
二叉树
堆排序
盒模型
box-sizing
transition
translate
call,apply,bind
闭包
内嵌函数
设计模式
数组方法
字符串方法
箭头函数
this
不能用作构造函数
事件循环
状态码
长连接
cookies,sessionStorage,loacalStorage
null undefined 指针,对象
浏览器缓存
display:none 回流
visible:hidden 重绘
setState执行机制
jsbridge
登录注册鉴权
前端路由
postMessage
hash
webScorket
service worker
web worker
css变量
viewport 1px
二维数组扁平化
金额千分位分割符
http方法
清除浮动
restful
PWA
riddle
1.XSS跨站脚本攻击(Cross Site Scripting)
1)通过
这样我们就可以获取别人的cookie信息了
2) 能过append
3.网络劫持攻击
很多的时候,我们的网站不是直接就访问到我们的服务器上的,中间会经过很多层代理,如果在某一个环节,数据被中间代理层的劫持者所截获,他们就能获取到使用你网站的用户的密码等保密数据。比如,我们的用户经常会在各种饭馆里面,连一些奇奇怪怪的wifi,如果这个wifi是黑客所建立的热点wifi,那么黑客就可以结果该用户收发的所有数据。这里,建议站长们网站都使用https进行加密。这样,就算网站的数据能被拿到,黑客也无法解开。
如果你的网站还没有进行https加密的化,则在表单提交部分,最好进行非对称加密–即客户端加密,只有服务端能解开。这样中间的劫持者便无法获取加密内容的真实信息了。
4.控制台注入代码
不知道各位看官有没有注意到天猫官网控制台的警告信息,如图4.1所示,这是为什么呢?因为有的黑客会诱骗用户去往控制台里面粘贴东西(欺负小白用户不懂代码),比如可以在朋友圈贴个什么文章,说:"只要访问天猫,按下F12并且粘贴以下内容,则可以获得xx元礼品"之类的,那么有的用户真的会去操作,并且自己隐私被暴露了也不知道。
5钓鱼
钓鱼也是一种非常古老的攻击方式了,其实并不太算前端攻击。可毕竟是页面级别的攻击,我们也来一起聊一聊。我相信很多人会有这样的经历,QQ群里面有人发什么兼职啦、什么自己要去国外了房子车子甩卖了,详情在我QQ空间里啦,之类的连接。打开之后发现一个QQ登录框,其实一看域名就知道不是QQ,不过做得非常像QQ登录,不明就里的用户们,就真的把用户名和密码输入了进去,结果没登录到QQ,用户名和密码却给人发过去了。
其实这种方式,在前端也有利用。下面,我们就来试试如果利用前端进行一次逼真的钓鱼。
1 首先,我们在xx空间里分享一篇文章,然后吸引别人去点击。
Debounce 和 Throttle 的原理及实现
当我们在处理诸如 resize 、 scroll 、 mousemove 和 keydown/keyup/keypress 等事件的时候,通常我们不希望这些事件太过频繁地触发,尤其是监听程序中涉及到大量的计算或者有非常耗费资源的操作。如果鼠标连续移动,那么浏览器就应该触发多个连续的 mousemove 事件,这意味着浏览器会在其内部计时器允许的情况下,根据用户移动鼠标的速度来触发 mousemove 事件。
Debounce
DOM 事件里的 debounce 概念其实是从机械开关和继电器的“去弹跳”(debounce) 衍生出来的,基本思路就是把多个信号合并为一个信号。
在 JavaScript 中, debounce 函数所做的事情就是, 强制一个函数在某个连续时间段内只执行一次,哪怕它本来会被调用多次 。我们希望在用户停止某个操作一段时间之后才执行相应的监听函数,而不是在用户操作的过程当中,浏览器触发多少次事件,就执行多少次监听函数。比如,在某个 3s 的时间段内连续地移动了鼠标,浏览器可能会触发几十(甚至几百)个 mousemove 事件,不使用 debounce 的话,监听函数就要执行这么多次;如果对监听函数使用 100ms 的“去弹跳”,那么浏览器只会执行一次这个监听函数,而且是在第 3.1s 的时候执行的。
现在,我们就来实现一个 debounce 函数。
/**
}, 200))
我们在处理防止用户连续快速点击按钮时就可以采用这种方法解决。
Throttle
throttle 的概念理解起来更容易,就是 固定函数执行的速率 ,即所谓的“节流”。正常情况下, mousemove 的监听函数可能会每 20ms(假设)执行一次,如果设置 200ms 的“节流”,那么它就会 每 200ms 执行一次。比如在 1s 的时间段内,正常的监听函数可能会执行 50(1000/20) 次,“节流” 200ms 后则会执行 5(1000/200) 次。
/**
*
网络
• OSI网络七层模型介绍?每层模型涉及的协议和理解
• TCP和udp的区别?
TCP面向连接,UDP面向无链接
TCP面向报文,UDP面向字节流
TCP提供可靠传输服务(数据顺序、正确性),UDP传输不可靠
TCP协议传输速度慢,UDP协议传输速度快
TCP协议对系统资源要求多(头部开销大),UDP协议要求少
• TCP建链过程和断开过程?为什么要三次握手,两次行不行?链接建立后传输过程中客户端异常的处理情况?
• 二三层网络转换原理
• http协议的了解
简单快速,无状态,灵活允许任意传输对象
请求行,请求头,请求体
响应状态行,消息报头,响应正文
请求方法:GET、POST的区别
• cookie和session的区别
• 介绍下浏览器输入淘宝网址到浏览器展示网页的过程
数据结构&算法
• 数组和链表的区别?应用场景
• 链表的插入、删除、反转链表
• 不用额外空间判断单链表是否循环链表
1.将所有遍历过的节点用某个结构存储起来,然后遍历每个节点,都在这个结构中查找是否遍历过。如果有遍历过,那就证明存在环。
这个结构,可以是hash,hash中的值存储的是节点的内存地址,
因此查找的操作所需时间O(1)
遍历的操作所需时间O(n)
hash存储空间所需额外的O(n)
【时间复杂度为O(n),空间复杂度为O(n)】
但是:因为使用了某结构存储,所以,违反了题目要求,要叉掉
2.最佳方案
【快慢指针】:需要两个指针,一个快指针:每次走两步,一个慢指针:每次走一步。
如果快慢指针能够相遇(如果快指针能够追上慢指针),就证明有环。
但是!!!这个方法存在问题。如果链表够长,而环又足够小,那么快指针将永远不会追上慢指针
所以,快慢指针只适合用于环出现在链表尾部的情况,也就是单链表环的问题,而无法解决链表存在循环的问题。
• 二叉树?二叉树的遍历?什么是平衡二叉树?二叉树深度?
• 如何判断是否二叉搜索树?
• 介绍一下散列表
数据库
• 乐观锁和悲观锁?使用场景?
• 如何查看SQL性能?
• 数据库索引?
• 数据库事务特性?事务的隔离级别?不同隔离级别对应的问题?
• 有以下表,查询平均成绩>60分的学生学号和平均成绩
select a.sno as “学号”, avg(a.score) as “平均成绩”
from
(select sno,score from sc) a
group by sno having avg(a.score)>60
C语言
• 能不能在整型中存放32768这个数?
整数类型可以存放从-32768~32767之间的任何数值。但是32768不在这个范围之内。
这个时候modifier是我们需要的东西。Long Int数据类型就可以存放这个数。
• “引用”与指针的区别是什么?
• 文件合并
• 文件最小化/文件压缩
• 使用CDN托管
• 缓存的使用
• 性能优化?
hybrid的原理
Click点击延迟的解决方案
浮点数计算精度丢失问题
javascript的eventloop
全局对象\闭包循环引用导致的内存泄漏\DOM节点子节点释放\timer计时器没有clear等)
前后端分离开发时你们项目怎么发布的
1.手动build后上传资源服务器(如果回答这个 就再问如何保证本地的包是安全的)
2.使用ci工具
常用的有以下几种:
Jenkins :借助 Jenkins 配合 gitlab 的 webhook 来做CI/CD
Circle CI : 强大,对 Github 友好
Travis CI:强大,对 Github 友好
Gitlab CI:Gitlab 自带 CI 环境
你们的项目内用了哪些代码规范工具 配置过哪些rules
1.eslint (例如基于 google ar)
2.prettier
3.stylelint
4.husky(无符合规范就不允许commit)
17.如何进行错误监控
前端错误的分类
• 即时运行错误(代码错误)
• 资源加载错误
错误的捕获方式
即时运行错误的捕获方式:
• try…catch
• window.onerror
资源加载错误:
• object.onerror(如img,script)
• performance.getEntries()
• Error事件捕获
延伸:跨域的js运行错误可以捕获吗,错误提示什么,应该怎么处理?
可以。
Script error
1.在script标签增加crossorigin属性
2.设置js资源响应头Access-Control-Allow-Orgin:*
上报错误的基本原理
采用Ajax通信方式上报
利用Image对象上报
浏览器有哪些缓存机制
1.缓存位置
Service Worker
Memory Cache(内存中的缓存)
Disk Cache(硬盘中的缓存)
2.缓存策略
强缓存(通过设置两种 HTTP Header 实现:Expires 和 Cache-Control 。强缓存表示在缓存期间不需要请求,state code 为 200)
协商缓存(缓存过期了,就需要发起请求验证资源是否有更新。协商缓存可以通过设置两种 HTTP Header 实现:Last-Modified 和 ETag
防抖的原理为触发事件的 n 时间后才执行,如果 n 时间内事件再次被触发,则以新触发的时间为标准,然后 n 事件后再执行
节流的原理为在持续触发事件时候,每隔一段时间执行一次。我们可以使用 time line 或者定时器来实现,或者二者结合实现。
: 如何解决移动端页面300ms延迟问题?
A: FastClick的解决方案,利用touchend时dispatch一个自定义的click事件,并且把浏览器行为的click事件通过event.preventDefault()的方法给阻止掉。
Q: 什么是点击穿透,以及如何解决点击穿透?
A: 假如页面上有两个元素A和B。B元素在A元素之上。我们在B元素的touchstart事件上注册了一个回调函数,该回调函数的作用是隐藏B元素。我们发现,当我们点击B元素,B元素被隐藏了,随后,A元素触发了click事件。 这是因为在移动端浏览器,事件执行的顺序是touchstart > touchend > click。而click事件有300ms的延迟,当touchstart事件把B元素隐藏之后,隔了300ms,浏览器触发了click事件,但是此时B元素不见了,所以该事件被派发到了A元素身上。如果A元素是一个链接,那此时页面就会意外地跳转。解决方案之一就是上面提到的FastClick。
Bug 复现
在一排序 UI 控件中,我们使用了 HTML 5 的 draggable 特性来处理拖拽内部元素使之进行排序的功能。之前都好好的,突然有用户反馈说 drag 的元素在 drop 的时候无论如何都会弹跳到列表的第一号位去。like
收到 Bug 反馈之后,立刻使用各种姿势重现,各种拖拽姿势始终重现不了。后续通过近距离「观察」用户是如何操作的,发现,他用的是「鼠标 」拖拽,我用的是 Tarckpad 拖拽,鼠标拖拽就能够必现了。
硬件设备还会影响拖拽的操作么!?遂为 Mac 接一个鼠标,开始调试 …
Bug 循因
找到 UI 控件代码,在使用 HTML5 draggable 特性的时候,有两个重要的监听事件,一个是 dragover 以及 dragend 。写了大致如下的代码:
// throttle 为 lodash 的 throttle 函数
const onDrag = throttle((e) => {
e.preventDefault();
e.dataTransfer.effectAllowed = ‘move’;
ref = locateNode(e);
placeNodeAt(ref);
}, 200);
const onDragEnd = (e) => {
e.preventDefault();
placeNodeAt(origRef);
sortNodeList(ref ? ref.dataset.id : null);
// …
};
document.addEventListener(‘dragover’, onDrag);
/* events fired on the draggable target /
document.addEventListener(‘drag’, onDrag);
/ events fired on the drop targets /
document.addEventListener(‘dragend’, onDragEnd);
onDrag 是在每次拖拽的时候以及拖拽到可以 drop 的对象上的时候触发的事件回调。由于这个回调的的触发频率是每几百毫秒一次,所以出于性能考虑,做了 200ms 的节流处理。
查出之所以会 locate 并插入到第一个节点的原因,是因为 throttle 回调函数中的 event 参数,它的 clientX 与 clientY 在最后一次始终为 0。而 locateNode 在计算相关排序位置的时候需要依赖这两个参数。
索性 Google 了一下,在 StackOverflow 以及 MDN 上有类似的描述:
/ events fired on the drop targets */
document.addEventListener(“dragover”, function (event) {
// prevent default to allow drop
event.preventDefault();
}, false);
event.preventDefault();
没错,就是 这个行为,如果不调用的话,就会出现最后一次 event 对象上的 clienX 以及 clientY 将为 0。那么为什么呢?查看 HTML Standard 相关文档发现(摘录了部分关键的信息,感兴趣的看这里 全文 ):
The dragover event handler specifies what feedback will be shown to the user, by setting the dropEffect attribute of the DataTransfer associated with the event. This event also needs to be canceled.
During the drag operation, the element directly indicated by the user as the drop target is called the immediate user selection. (Only elements can be selected by the user; other nodes must not be made available as drop targets.) However, the immediate user selection is not necessarily the current target element, which is the element currently selected for the drop part of the drag-and-drop operation.
The immediate user selection changes as the user selects different elements (either by pointing at them with a pointing device, or by selecting them in some other way). The current target element changes when the immediate user selection changes, based on the results of event listeners in the document, as described below.
Initialize event’s mouse and key attributes initialized according to the state of the input devices as they would be for user interaction events. If there is no relevant pointing device, then initialize event’s screenX, screenY, clientX, clientY, and button attributes to 0.
简而言之就是,如果不 preventDefault,最后一次即释放前 event 对象的 traget 对象所关联的 immediate user selection 将会按照默认行为去关联,默认关联的 drop effect 在我没有配置的情况下不存在,这就导致了抛出的事件的 clientX 与 clientY 为 0。而正是 throttle 的时延导致了部分事件 preventDefault() 没有被调用,而出现问题。
那么为什么在 Trackpad 的情况下又是 OK 的呢?怀着侥幸的心理,我缩小了 throttle 函数的第二个参数值,即 throttle 的间隔时间为 10ms。惊奇间发现,Trackpad 同样也出现该问题了。
这样一来,就可以猜测是因为 Trackpad 在触发 dragEnd 的事件时延是大于 200ms 的,即 dragOver 执行时 dragEnd 还未结束,因此 immediate user selection 对应的 target 还存在,clientX / clientY 返回自然就不是 0 了。而之前用鼠标的时候,dragEnd 先执行,dragOver 后执行,dragOver 后执行的时候 target 已经不存在了。
解决方案 & 启迪
• dragOver 的时候每次都调用 preventDefault ,而让 throttle 函数包裹在定位和节点变换的函数之上。
• 至于 trackPad 的对 dragEnd 时延问题,只需要保证 dragEnd 执行之后,dragOver 的回调 cancel 掉即可。
未来在处理这类事件的时候确实得考虑到「设备输入」导致的时延不尽相同的问题,异步事件处理的时候的确需要多加小心,不能够假定先后顺序就一定是如此。
更多详情看这里
12.前端路由的原理
什么是路由?简单的说,路由是根据不同的 url 地址展示不同的内容或页面
使用场景?前端路由更多用在单页应用上, 也就是SPA, 因为单页应用, 基本上都是前后端分离的, 后端自然也就不会给前端提供路由。
前端的路由和后端的路由在实现技术上不一样,但是原理都是一样的。在 HTML5 的 history API 出现之前,前端的路由都是通过 hash 来实现的,hash 能兼容低版本的浏览器。
两种实现前端路由的方式
HTML5 History两个新增的API:history.pushState 和 history.replaceState,两个 API 都会操作浏览器的历史记录,而不会引起页面的刷新。
Hash就是url 中看到 # ,我们需要一个根据监听哈希变化触发的事件( hashchange) 事件。我们用 window.location 处理哈希的改变时不会重新渲染页面,而是当作新页面加到历史记录中,这样我们跳转页面就可以在 hashchange 事件中注册 ajax 从而改变页面内容。
优点
从性能和用户体验的层面来比较的话,后端路由每次访问一个新页面的时候都要向服务器发送请求,然后服务器再响应请求,这个过程肯定会有延迟。而前端路由在访问一个新页面的时候仅仅是变换了一下路径而已,没有了网络延迟,对于用户体验来说会有相当大的提升。
更多内容请看这里
缺点
使用浏览器的前进,后退键的时候会重新发送请求,没有合理地利用缓存。
13.Restful API是什么
Restful的意思就是表现层状态转化。
应该尽量将API部署在专用域名之下。如果确定API很简单,不会有进一步扩展,可以考虑放在主域名下。
浏览器缓存机制剖析
缓存一直是前端优化的主战场, 利用好缓存就成功了一半. 本篇从http请求和响应的头域入手, 让你对浏览器缓存有个整体的概念. 最终你会发现强缓存, 协商缓存 和 启发式缓存是如此的简单 .
浏览器对于请求资源, 拥有一系列成熟的缓存策略. 按照发生的时间顺序分别为存储策略, 过期策略, 协商策略, 其中存储策略在收到响应后应用, 过期策略, 协商策略在发送请求前应用. 流程图如下所示
废话不多说, 我们先来看两张表格.
1.http header中与缓存有关的 key.
2.缓存协商策略用于重新验证缓存资源是否有效, 有关的key 如下 .
下面我们来看下各个头域(key)的作用.
Cache-Control
浏览器缓存里, Cache-Control是金字塔顶尖的规则, 它藐视一切其他设置, 只要其他设置与其抵触, 一律覆盖之.
不仅如此, 它还是一个复合规则, 包含多种值, 横跨 存储策略, 过期策略 两种, 同时在请求头和响应头都可设置.
语法为: “Cache-Control : cache-directive”.
Cache-directive共有如下12种(其中请求中指令7种, 响应中指令 9 种):
假设所请求资源于4月5日缓存, 且在4月12日过期.
当max-age 与 max-stale 和 min-fresh 同时使用时, 它们的设置相互之间独立生效, 最为保守的缓存策略总是有效. 这意味着, 如果max-age=10 days, max-stale=2 days, min-fresh=3 days, 那么:
根据max-age的设置, 覆盖原缓存周期, 缓存资源将在4月15日失效(5+10=15);
根据max-stale的设置, 缓存过期后两天依然有效, 此时响应将返回110(Response is stale)状态码, 缓存资源将在4月14日失效(12+2=14);
根据min-fresh的设置, 至少要留有3天的新鲜期, 缓存资源将在4月9日失效(12-3=9);
由于客户端总是采用最保守的缓存策略, 因此, 4月9日后, 对于该资源的请求将重新向服务器发起验证.
Pragma
http1.0字段, 通常设置为Pragma:no-cache, 作用同Cache-Control:no-cache. 当一个no-cache请求发送给一个不遵循HTTP/1.1的服务器时, 客户端应该包含pragma指令. 为此, 勾选☑️ 上disable cache时, 浏览器自动带上了pragma字段. 如下:
Expires
Expires:Wed, 05 Apr 2017 00:55:35 GMT
即到期时间, 以服务器时间为参考系, 其优先级比 Cache-Control:max-age 低, 两者同时出现在响应头时, Expires将被后者覆盖. 如果Expires, Cache-Control: max-age, 或 Cache-Control:s-maxage 都没有在响应头中出现, 并且也没有其它缓存的设置, 那么浏览器默认会采用一个启发式的算法, 通常会取响应头的Date_value - Last-Modified_value值的10%作为缓存时间.
如下资源便采取了启发式缓存算法 .
其缓存时间为 (Date_value - Last-Modified_value) * 10%, 计算如下:
const Date_value = new Date(‘Thu, 06 Apr 2017 01:30:56 GMT’).getTime();
const LastModified_value = new Date(‘Thu, 01 Dec 2016 06:23:23 GMT’).getTime();
const cacheTime = (Date_value - LastModified_value) / 10;
const Expires_timestamp = Date_value + cacheTime;
const Expires_value = new Date(Expires_timestamp);
console.log(‘Expires:’, Expires_value); // Expires: Tue Apr 18 2017 23:25:41 GMT+0800 (CST)
可见该资源将于2017年4月18日23点25分41秒过期, 尝试以下两步进行验证: