1、js解析过程:先定义 后执行
a(); // undefined
var b=3;
function a(){
var c=2;
alter(b);
}
// 解析过程:先定义 后执行
// 定义:
var b
function a(){};
// 执行:赋值、函数执行
a();
// 此时a的域
// 定义:
var c
// 执行:
alter(b);
// a函数结束
// 执行
b=2
注意:定义阶段,函数与变量同样的命令,最后会变成函数,因为函数优先级高。
2、事件冒泡
理解:当元素和子元素同时存在同一个事件时,从子元素上产生事件的时候,事件会传递到父元素上。
// 阻止冒泡
e.stopPropagation()
3、事件捕获
理解:元素和子元素同时存在同一个事件时,当父子元素的事件启用捕获的时候,点击父元素他会往子元素传递。
box.addEventListener('click' , ()=>{} , true); // 第三个参数就是是否开启捕获
4、js隐式转换
隐式转换:当使用 == 的时候,就代表 比较 的意思,当两边类型不同的时候,就会进行隐式转换。
转换规则:对象 --> 字符串 --> 数值 <-- 布尔
// 对象与布尔比较
[] == true // [] --> '' --> 0 , true --> 1 ,双方结果会不一样,所以是false
// 对象与字符串
[1,2,3] == '1,2,3' // [1,2,3] --> '1,2,3' 结果是true
// 对象与数字
[1] == 0 // [1] --> '1' --> 1 结果是false ,与0不相等
5、js强制转换
注意:'' NAN 0 null underfined 强制转换为布尔值时 结果是 false ,其他的都是true
[] == false
![] == false
// 上面的结果都是true
// [] 会隐式转换为false
// 使用非! , 会把[]强制转换,所以为true,再使用!,则变成false
6、请求相关
http 传输过程中是明文的 https 是结合ssl连接的,服务器收到请求后会把网站的证书(里面有公钥)返回给客户端,客户端使用公钥加密内容(会话密钥),然后传输给服务器,服务器自然就可以使用密钥解密内容(会话密钥),自此服务器和客户端就可以使用这个会话密钥进行通信。
建立连接的tcp三次握手: 服务器端确认自己可以接受客户端的报文段,客户端确认服务端收到自己的报文并且自己也确认可以接收服务端发生的报文端,服务端收到客户端的报文
状态码分类:
- 1xx 服务器收到请求
- 2xx 请求成功
- 3xx 重定向
- 4xx 客户端错误
- 5xx 服务端错误
状态码:
- 304 未修改,服务器不会返回任何资源,客户端会访问缓存的资源
- 400 请求的语法错误
- 401 请求的用户信息错误
- 405 请求的方法被禁止的
- 500 服务器内部错误
- 502 服务器作为网关或者代理的时候,从其他服务器接收到一个无效的响应
请求缓存:浏览器缓存请求的数据
如何辨别缓存:服务器会记录一个最后修改时候,浏览器缓存的时候,会接收服务器的最后修改时间,当当前浏览器的最后缓存时间和服务器的一致时就不请求,不一致的时候就再次请求
- 强缓存:利用http头中的Expires和Cache-Control两个字段来控制的,用来表示资源的缓存时间(浏览器控制)
- 协商缓存 :让服务器通过最后修改时间去判断是否需要刷新
过程:
1、请求后,也会把请求头的内容发送给服务器,请求头上是携带一些缓存的信息,然后根据header的cache-control和expires判断一下缓存的内容是否过期(浏览器端设置的过期时间)。
2、客户端通过If-None-Match将最后修改时间传给服务器,服务器接收到后进行对比,一致的话返回304状态码,浏览器继续使用缓存的内容,不一致就返回200,使用新返回的数据。
7、url在浏览器上过程
首先获取这个服务的ip,看下本地缓存有没有,得到ip后通过端口构造一个http请求,服务端就会返回html文件让浏览器解析,根据html来构建dom树,构造的时候如果遇到js内容就会停止等js解析完,然后解析外部样式,内部样式,内联样式构建cssom树,构造完成合成渲染树,然后排除非视觉标签,如mete script display:none 然后进行布局渲染,有图片就并行下载
8、bfc,创建一个隔离的容易,与外面不相影响
使用bfc的方法:
1、浮动
2、绝对定位
3、盒子格式(display 为 inline-block、table-cells、flex)
4、overflow 除了 visible 以外的值 (hidden、auto、scroll)
// 情景1,上下都是块盒子,上下都使用margin,marign重叠
html
<div class="demo1"></div>
<div class="demo2"></div>
css
.demo1{width: 200px;height: 200px;background-color: red;margin-bottom: 20px;}
.demo2{width: 200px;height: 200px;background-color: black;margin-top: 30px;}
9、跨域
同源策略:协议+域名+端口 三者相同
1、jsonp跨域
把js、css、img等静态资源分到另外一台域名服务器上,通过类似script等标签去引入是没有跨域问题的
10、事件循环
栈:同步任务,如变量和函数的初始化,里面的内容按顺序执行,保存引用类型引入的数据。内部是自动分配内存的
堆:声明的内容,引用类型的数据。动态分配内容,需要自己释放
队列:异步内容,如promise,请求,定时器等等
事件循环过程:浏览器按顺序执行栈里面的内容,然后队列里面的异步内容产生的回调函数就会推到栈中,这个过程是不断循坏的,不断去检测队列中有没有产生回调函数
11、任务处理顺序
宏任务:其实就是正常栈里面的任务,
script(整体代码)
setTimeout
setInterval
I/O
UI交互事件
postMessage
MessageChannel
setImmediate(Node.js 环境)
微任务:正常的执行顺序是处理完js同步代码后,就会执行异步的回调函数,这个就是微任务
Promise.then
Object.observe
MutationObserver
process.nextTick(Node.js 环境)
12、js数字相加的转换
1、0.2+0.1>0.3问题
由于js的计算是转成二进制的,但是0.1是一个无限的数,并且js只取52位,所以计算的时候拿到的0.1 大于0.1的,所以大于0.3
2、0.2+0.3=0.5的问题
由于0.2 和 0.3的二进制刚好是52位
3、那0.1打印的时候为什么还是0.1:因为打印的时候会把二进制转成10进制,在转成字符串
13、script 中的 defer 和 async
1、script 单独标签,标签内容下载和解析,会阻断后面的html内容的解析 2、script async 下载内容的时候不会阻断,解析的时候会阻断 3、script defer 下载的时候不会阻断,会在html内容解析完再解析下载的内容
14、重绘与回流
回流:计算节点的位置和几何信息
重绘:知道了哪些节点是可见的,以及可见节点的样式和具体的几何信息(位置、大小),那么我们就可以将渲染树的每个节点都转换为屏幕上的实际像素
发生回流的情况:dom和元素或dom内容变化,窗口大小变化等等 发生回流一定发生重绘,而发生重绘不一定发生回流(比如颜色修改,这时候不会影响节点,所有只发生重绘)
15、优雅运算符 1、? 的使用,如ts中的 ? 一样
/* 可选运算符 ? 、 ??,只可用于读取值,不可以使用于赋值 */
// 1、
let obj = {
a: 123,
fn: () => {
console.log("方法被调用了");
},
};
/* 静态使用 */
console.log(obj?.a); // 123
console.log(obj?.b); // undefined
// 动态使用
let arr = ["a", "b"];
arr.map((item) => {
// 123
// undefined
console.log(obj?.[item]);
//
obj?.fn()
});
// 2、?? 双重问号解决 ? 找不到后的默认值问题
console.log(undefined ?? '默认值'); // 默认值
console.log(obj.a?.c?.d?.e ?? '不存在这么多值');
// 3、逻辑空分配
// (?? =) 其实就是结合 ?? 使用赋值,x不存在的时候,就赋值y给x,x限于 null 和underfind
let x
let y = 123
x ??= y
console.log(x); // 123
// (x ||= y) 等同于 x || (x = y) 和上面的意思一样,但不一样的是 x 限于所有强转后是false的值
// (x &&= y) x存在的时候赋值