一、eventLoop
setTimeout,ajax等异步和dom事件都是使用回调,基于eventLoop
执行同步代码,遇到异步代码存到另一个地方,同步代码执行完毕,开始启动eventLoop,不断询问callback queue是否有代码可执行,异步代码执行完毕的时候,会把回调推到callback queue内,eventLoop访问到代码,开始到call stack执行代码,执行完毕之后弹出
js和dom渲染共用一个进程
call Stack空闲的时候 -> 尝试DOM渲染 -> 再触发eventLoop
二、promise
then和catch正常都是返回一个resolved的,里面要是有报错,则直接rejected
resolve / reject / then / catch / all / race
allSettled :等到所有promises都完成(每个promise返回成功或失败),返回一个promise,并带有一个对象数组,每个对象对应每个promise的结果
any(当其中的一个promise 成功,就返回那个成功的promise的值。)
三、async && await
async返回的是promise对象 ,
await相当于promise.then (返回的不是promise的话,就用promise.resolve包裹起来返回,如果promise它reject了,就报错,用try...catch捕获)
四、异步的本质
异步的本质就是回调~
await后面的代码,都可以看成callback里的内容,就是异
五、异步遍历(for...of)
for ... in : 遍历获取的是对象的键名
for... of: 遍历获取的是对象的键值,等上一个有结果了,才执行下一个(异步循环)
六、宏任务和微任务
宏任务:setTimeout / setInterval / ajax / dom事件,DOM渲染完成之后触发回调,浏览器规定
微任务:promise,DOM渲染完成之前触发,ES6语法规定
1、call Stack空闲的时候(同步任务完成)
2、执行当前的微任务
3、尝试DOM渲染
4、 最后触发eventLoop
七、DOM(Document Object Modal)
1、数据结构:是从html解析出来树形结构
2、常用API:
获取节点:getElementById(),getElementsByTagName(数组) , getElementsByClassName(数组),querySelectorAll(数组)
property:以js.语法操作的属性,node.style.xxx / node.className 修改对象属性,不体现到html中(推荐)
attribute:getAttribute() / setAttribute(),修改html属性,体现到html结构中
两者都会有可能引起重新渲染
4、节点操作
新建:const p1 = document.createElement('p')
插入:div1.appendChild(p1)
移动:将现有节点appendChild到其他元素下面
父元素:p1.parentNode
子元素列表:div1.childNodes,nodeType === 1的是元素节点
删除子元素:div1.removeChild(p1)
3、优化dom操作性能
避免频繁操作
DOM查询缓存
将频繁操作改为一次操作:
const frag = document.createDocumentFragment()
八、BOM(Browser Object Modal)
1、识别浏览器类型
const ua = window.navigator.userAgent
浏览器类型检测方法
2、分解url
location.href : 全
location.protocal : https
location.search : 参数(?a=2&b=3)
location.hash : hash值
location.host : www.baidu.com
location.pathname : 路径
3、history:
history.back()
history.forword()
九、事件
1、阻止事件冒泡
stopPropagation / cancelBubble
2、阻止默认行为
preventDefault / return false
3、事件监听器
addEventListener / attachEvent
removeEventListener / detachEvent
4、事件代理
基于事件冒泡
十、同源(协议、域名、端口)
css / js / img可无视同源策略
img可用于统计打点(一般是1px *1px 的gif)
link和script可用CDN
script可实现JSONP进行跨域
十一、ajax
readyState 状态 状态说明
(0)未初始化:表示对象已经存在
(1)载入:表示正在向服务端发送请求。
(2)载入完成:表示已经接收完全部响应数据。并为下一阶段对数据解析作好准备。
(3)交互:表示正在解析数据。
(4)完成:表示数据解析完毕,可以通过XMLHttpRequest对象的相应属性取得数据。
概而括之,整个XMLHttpRequest对象的生命周期应该包含如下阶段:
创建-初始化请求-发送请求-接收数据-解析数据-完成
十二、http
1、状态码
1xx:服务器收到请求
2xx: 请求成功,200
3xx: 重定向,301(永久重定向),302(临时重定向),304(命中协商缓存,资源未被修改),
4xx:客户端错误,404(找不到),401(无权限),403(forbidden)
5xx: 服务端错误,500,503(服务器正在启动),502(bad request),504(网关超时)
2、headers
requestHeaders:
Accept:浏览器可接受数据格式
Accept-Encoding: 浏览器可接受的压缩算法,gzip
Accept-Language: 浏览器可接受的压缩算法,zh-CN
Connection:keep-alive(长链接)
cookie: 同域自动带
host: 请求域名
User-Agent:浏览器信息
Content-type:发送数据的格式
responseHeaders:
Content-type:返回数据的格式
Content-length: 返回数据的大小,字节
Content-Encoding: 返回数据的压缩算法,gzip
set-cookie: 服务器设置cookie
cache-control / expires / etag / last-modified / if-modified-since / if-none-match
十三、Restful-API
请求分成增删改查,4种methods去请求,用method表示操作类型
十四、http缓存
js / css / img可以被缓存
1、强制缓存:命中返回200状态码
expires: http1.0的属性,权重低于cache-control
cache-control : response headers里,控制强制缓存的逻辑,
max-age: 最大缓存时间,s
no-cache: 跳过强制缓存,询问服务端(走协商缓存)
no-store: 不缓存
public: 浏览器和中间服务器都可缓存
private: 只有浏览器可以缓存
2、 协商缓存:命中返回304状态码
response header
Last-modified: 资源最后修改时间,只能精确到秒级
Etag : 资源的唯一标识(计算起来比较耗性能),更准确
requset header
If-Modified-Since
If-None-Match
权重:Etag > Last-Modified
3、刷新对缓存的影响:
①、正常操作:地址栏输入url,跳转连接,浏览器前进后退
强制缓存,协商缓存都有效
②、 手动刷新:F5 ,点击刷新,右键刷新
强制缓存失效,协商缓存都有效
③、强制刷新: Ctrl + F5
全部失效
十五、从输入url到出页面
1、DNS解析
2、发起请求
3、 请求返回
4、生成DOM Tree
5、生成CSSOM
6、 DOM Tree和CSSOM合成render Tree
7、根据render Tree渲染页面
8、遇到js暂停渲染,优先加载执行js,完成再继续渲染
9、渲染完成
十六、window.onload和DOMContentLoaded
window.onload: 全部资源加载完成,触发
DOMContentLoaded:只有dom渲染完成就触发
十七、TCP && UDP
十八、tree-shaking
依赖于es6的module特性:
1、只能作为模块顶层的语句出现
2、import 的模块名只能是字符串常量
3、import binding 是 immutable(一成不变)的
也就是说es6的mudule是确定的,静态的,tree-shaking只能识别静态代码(不执行代码),从字面量分析,所以wepack和rollup一定要基于es6才能实现tree-shaking
wepack和rollup本身是不能进行tree-shaking的,是uglify操作的
特殊情况:
tree-shaking不能进行跨文件优化,
tree-shaking对函数效果较好
十九、for/forEach/for...in/for...of
1、for只能遍历数组,遍历数组的下标作为key,可以break,不可以return
2、forEach也只能遍历数组,遍历数组的值,但是不能用break退出循环体,也不能从循环体return出啥来
3、for...in即可遍历数组,也可以遍历对象,遍历的是数组的下标或者是对象的key,break可以终止,
4、for...of只能遍历数组,遍历的是数组的值,break可以终止,
return只能用在函数体
continue/break 只能用在for、for/of、for/in、while、do/while的循环体
二十、安全
1、XSS(跨站请求攻击)
①、反射
就是用户访问的时候,部分不是我们自己的代码会在浏览器执行,造成问题,信息泄露啥的。
就是可能搜索的地方,用户输入个js代码,发送个啥数据给我,我可能就干坏事了,
但是搜索只能是自己搜索,你总没有超能力控制受害者输入啥吧,那就可能从url入手,携带恶意代码,被浏览器拿来执行
②、存储
用户的输入被发送并存储到数据库,下次读取的时候,造成问题
就像是评论,我评论个一个恶意js代码,你再看到时候,就把你的信息发给我,我是不是就要坏事儿了
③、DOM:我不知道
防御:
httpOnly
转义
2、xsrf(跨站请求伪造)
攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的
受害者登陆过被攻击网站,并在本地保存着凭证
受害者点击第三方网站,执行代码,伪造是受害者的请求
被攻击网站确认时受害者的请求,执行代码
防御:
token
同源
二十一、css module
css-loader有配置项在,在配置css-loader的时候,options的配置项
六、代码规范yorkie
lint && commitMessage校验
gitHooks:{
"pre-commit": 'lint-staged',
"commit-msg" : "commitlint -e $GIT_PARAMS"
}
二十二、scrollTop
scrollTop:元素被卷去的高度
scrollHeight:算上被卷去的总高度,内容不超出盒子高度时为盒子的clientHeight
offsetWidth 水平方向 width + 左右padding + 左右border
clientWidth 水平方向 width + 左右padding
offsetTop 获取当前元素到 定位父节点 的top方向的距离
getBoundingClientRect() 获取元素到body
* bottom: 元素底边(包括border)到可视区最顶部的距离
* left: 元素最左边(不包括border)到可视区最左边的距离
* right: 元素最右边(包括border)到可视区最左边的距离
* top: 元素顶边(不包括border)到可视区最顶部的距离
* height: 元素的offsetHeight
* width: 元素的offsetWidth
* x: 元素左上角的x坐标
* y: 元素左上角的y坐标
获取以上元素都会触发回流,慎用
八、回流和重绘
会导致回流的操作:
页面首次渲染。
浏览器窗口大小发生改变。
元素尺寸或者位置发生改变。
元素内容变化(文字数量或者图片大小发生改变)。
元素字体大小的改变。
添加或者删除可见的DOM元素。
激活CSS伪类 (eg::hover)。
查询某些属性或调用某些方法。
一些常用且会导致回流的属性和方法。
clientWidth、clientHeight、clientTop、clientLeft
offsetWidth、offsetHeight、offsetTop、offsetLeft
scrollWidth、scrollHeight、scrollTop、scrollLeft
scrollIntoView()、scrollIntoViewIfNeeded()
getComputedStyle()
getBoundingClientRect()
scrollTo()
二十三、setTimeout && requsetAnimationFrame
1、setTimeout是异步执行任务,放进任务队列,可能造成卡顿,页面不可见的情况下,会继续在后台执行,损耗cpu,
2、requsetAnimationFrame,屏幕的刷新频率是每秒60帧,也就是每16.67ms刷新一次。requsetAnimationFrame会在页面不可见的时候,不执行回调,减少损耗cpu资源,可以取消,该函数返回一个id,使用cancelAnimationFrame(id)取消。由系统来决定回调函数的执行时机,跟着系统的刷新频率走,保证回调函数在屏幕每一次的刷新间隔中只被执行一次,但是兼容性不太好,需要优雅降级
二十四、数组方法
forEach:不修改原数组,不能break, continue, return,跳过后面的代码,进行下一次循环
map:不修改原数组,返回新数组,不能break,可以return,跳过后面的代码,进行下一次循环
函数体都是return,for循环体都是continue && break;
pop,shift返回被删除或者被新增的那个元素,unshift push返回新数组的长度
二十五、关于new
函数内,不明确return什么的时候,默认是返回 undefined,入砂锅是new操作符的话,默认返回的是this对象。但是但是但是!!!如果明确了return,那不管是直接执行还是new操作,返回的都是return的东西。
如果是return对象,且new操作了,那么被返回的对象的原型是不指向该类的原型的,也就是说,原型链并不是类的原型链了哦