JS知识整理

JS

window.onload和$(document).ready()的区别,浏览器加载转圈结束时哪个时间点?

window.onload是等到页面全都加载完才开始执行,且只能有一个window.onload,如果有多个只会执行最后一个
$(document).ready()等到DOM节点加载完开始执行

setTimeout 和 setInterval 区别,如何互相实现?

setTimeout是指在指定时间后执行setTimeout内方法,setInterval是指每过指定时间执行代码。

1
2
3
4
5
6
7
8
9
10
11
12
function setInter(time, func) {
setTimeout(function() {
func()
setInter()
}, time)
}
function setTime(time, func) {
let setInter = setInterval(function() {
func()
clearInterval(setInter)
}, time)
}

setTimeout和requestAnimationFrame区别

setTimeout是固定时间后执行,requestAnimationFrame是根据屏幕刷新频率来执行

form表单当前页面无刷新提交?target iframe;

闭包以及作用域

作用域是可访问变量的集合,可以分为全局作用域和局部作用域。

闭包就是将函数内部和函数外部连接起来的一座桥梁

this是在函数运行时,在函数体内部自动生成的一个对象,只能在函数体内部使用

JavaScript设计模式

单例模式
适配器模式
代理模式
发布-订阅模式
策略模式
迭代器模式

JSON.stringify深拷贝的缺点

  1. 如果obj里面有时间对象,则JSON.stringify后再JSON.parse的结果,时间将只是字符串的形式,而不是对象的形式
  2. 如果obj里有RegExp(正则表达式的缩写)、Error对象,则序列化的结果将只得到空对象;
  3. 如果obj里有函数,undefined,则序列化的结果会把函数或 undefined丢失;
  4. 如果obj里有NaN、Infinity和-Infinity,则序列化的结果会变成null
  5. JSON.stringify()只能序列化对象的可枚举的自有属性,例如 如果obj中的对象是有构造函数生成的, 则使用JSON.parse(JSON.stringify(obj))深拷贝后,会丢弃对象的constructor;
  6. 如果对象中存在循环引用的情况也无法正确实现深拷贝

浏览器地址 输入URL后都发生了什么?

  1. 解析URL地址得到IP地址:dns解析
  2. 客户端拿到IP地址进行tcp连接:三次握手
  3. 连接成功后发送HTTP请求:请求行、请求头、请求体
  4. 服务器处理并响应请求:响应行,响应头、响应体
  5. 浏览器解析渲染页面:构建dom树 -> 构建render树 -> 布局render树 -> 绘制render树
  6. 连接结束:这是tcp连接不会马上关闭因为HTTP1.1设置了keep-alive为true,标签关闭时会结束tcp连接四次挥手

CSS

HTML方面能够结合各个浏览器api描述常用类库的实现。

css方面能够结合各个概念,说明白网上那些hack方案或优化方案的原理

margin坍塌

就是当两个兄弟块元素同时有margin-top和margin-bottom时,两个块级元素上下间距变为其中最大值,而不是两个值相加的值,水平方向不会出现这样的情况

伪类和伪元素区别

伪类用于当已有元素处于的某个状态时,为其添加对应的样式,这个状态是根据用户行为而动态变化的。比如说,当用户悬停在指定的元素时,我们可以通过:hover 来描述这个元素的状态。虽然它和普通的 css 类相似,可以为已有的元素添加样式,但是它只有处于 dom 树无法描述的状态下才能为元素添加样式,所以将其称为伪类。

伪元素用于创建一些不在文档树中的元素,并为其添加样式。比如说,我们可以通过:before 来在一个元素前增加一些文本,并为这些文本添加样式。虽然用户可以看到这些文本,但是这些文本实际上不在文档树中。
还有像:first-letter, :first-line, ::before ::after

CSS的继承属性(部分)

font-size:设置字体的尺寸
text-indent:文本缩进
text-align:文本水平对齐
text-shadow:设置文本阴影
line-height:行高
元素可见性:visibility
光标属性:cursor

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新单位,view width的简写,是指可视窗口的宽度。假如宽度是1200px的话。那10vw就是120px
css3新单位,view height的简写,是指可视窗口的高度。假如高度是1200px的话。那10vh就是120px

垂直居中

单行文本

  1. 若元素是单行文本, 则可设置 line-height 等于父元素高度

行内块级元素
2. 若元素是行内块级元素, 基本思想是使用display: inline-block, vertical-align: middle和一个伪元素让内容块处于容器中央.

.parent::after, .son{
display:inline-block;
vertical-align:middle;
}
.parent::after{
content:’’;
height:100%;
}
元素高度不定
3. 可用 vertical-align 属性, 而vertical-align只有在父层为 td 或者 th 时, 才会生效, 对于其他块级元素, 例如 div、p 等, 默认情况是不支持的. 为了使用vertical-align, 我们需要设置父元素display:table, 子元素 display:table-cell;vertical-align:middle;

优点

元素高度可以动态改变, 不需再CSS中定义, 如果父元素没有足够空间时, 该元素内容也不会被截断.
缺点

IE6~7, 甚至IE8 beta中无效.
4. flex
5. 可用 transform , 设置父元素相对定位(position:relative), 子元素如下css样式:

1
2
3
4
5
6
7
.son{
position:absolute;
top:50%;
-webkit-transform: translate(-50%,-50%);
-ms-transform: translate(-50%,-50%);
transform: translate(-50%,-50%);
}

优点

代码量少
缺点

IE8不支持, 属性需要追加浏览器厂商前缀, 可能干扰其他 transform 效果, 某些情形下会出现文本或元素边界渲染模糊的现象.

网络

知道websocket用法,包括但不限于:鉴权,房间分配,心跳机制,重连方案等

https握手

首先客户端发起请求到服务端,服务端处理后发送一个公钥给客户端
客户端进行验证公钥,看公钥是否有效和是否过期
客户端验证通过会产生随机值key,然后用公钥进行加密回传给服务端
服务端用私钥解密后获得客户端的随机值key
利用随机值key加密数据后传输给客户端
客户端利用key值进行解密数据
客户端获取真正的数据

http2

二进制分帧
多路复用
服务器推送
头部压缩

ajax请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let xhr = new XMLHttpRequest()
document.cookie = 'name=jun' // cookie不能跨域
xhr.withCredentials = true // 前端设置是否带cookie
xhr.open('PUT', 'http://localhost:4000/getData', true)
xhr.setRequestHeader('name', 'jun')
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
console.log(xhr.response)
//得到响应头,后台需设置Access-Control-Expose-Headers
console.log(xhr.getResponseHeader('name'))
}
}
}
xhr.send()

框架

单页面应用原理

只有一张Web页面的应用,是一种从Web服务器加载的富客户端,单页面跳转仅刷新局部资源 ,公共资源(js、css等)仅需加载一次,常用于PC端官网、购物等网站

vue修饰符

v-model

  1. .lazy
  2. .trim
  3. number
    事件修饰符
  4. .stop阻止事件冒泡
  5. .prevent阻止事件默认行为
  6. .once只执行一次
  7. .native
  8. .capture事件捕获
  9. .passive 相当于onscroll事件整了一个.lazy修饰符

v-bind

  1. .sync v-bind @update的语法糖
  2. .camel驼峰

工程化工具

知道webpack打包链路,知道plugin生命周期,知道怎么写一个plugin和loader。

知道常见loader做了什么事情,能几句话说明白,比如babel-loader,vue-loader。

能结合性能优化聊webpack配置怎么做,能清楚说明白核心要点有哪些,并说明解决什么问题,需要哪些外部依赖,比如cdn,接入层等。

了解异步模块加载的实现原理,能口喷代码实现核心逻辑。

通过jsonp方式动态创建script标签异步加载对应 chunk,并缓存到 promise 的 resolve 中,并标记对应 chunk 已经加载
https://juejin.im/post/6844904033681948686#heading-8

webpack执行过程

  1. 初始化参数:从配置文件(默认webpack.config.js)和shell语句中读取与合并参数,得出最终的参数
  2. 开始编译(compile):用上一步得到的参数初始化Comiler对象,加载所有配置的插件,通过执行对象的run方法开始执行编译
  3. 确定入口:根据配置中的entry找出所有的入口文件
  4. 编译模块:从入口文件出发,调用所有配置的Loader对模块进行翻译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过处理
  5. 完成编译模块:经过第四步之后,得到了每个模块被翻译之后的最终内容以及他们之间的依赖关系
  6. 输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的chunk,再将每个chunk转换成一个单独的文件加入输出列表中,这是可以修改输出内容的最后机会
  7. 输出完成:在确定好输出内容后,根据配置(webpack.config.js && shell)确定输出的路径和文件名,将文件的内容写入文件系统中(fs)

webpack优化

打包时间速度优化:

  1. 优化loader配置:优化文件搜索范围,缓存babel编译过的文件
  2. HappyPack开启多线程打包
  3. DllPlugin
  4. 优化resolve: alias:可以通过别名的方式来映射一个路径,能让 Webpack 更快找到路径。extensions:减少后缀列表

    减少体积

  5. Tree Shaking
  6. Scope Hoisting 尽可能的合并打包出来的模块打一个函数中去
  1. 按需加载,将每个路由页面单独打包为一个文件。当然不仅仅路由可以按需加载,对于 loadash 这种大型类库同样可以使用这个功能

性能优化

http层面:

  1. 减少HTTP请求
  2. 使用http2
  3. 使用cdn
  4. 使用缓存
  5. 服务端渲染

css:

  1. 使用icon,不会失真。还有一个优点是生成的文件特别小
  2. 图片优化,延迟加载降低图片质量
  3. 压缩文件
  4. 通过 webpack 按需加载代码,提取第三库代码,减少 ES6 转为 ES5 的冗余代码
  5. 使用 requestAnimationFrame 来实现视觉变化
  6. 使用css3动画,降低css新选择器复杂性

JS

  1. 减少重拍重绘
  2. 时间代理
  3. 使用switch语法
  4. 开启多线程webworker

L型输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function a(arr) {
let result = []
while (arr.length) {
for (let i = 0; i < arr.length; i++) {
if (i === arr.length - 1) {
result.concat(arr[i])
arr.pop()
} else {
result.push(arr[i].shift())
}
}
}
return result
}