Javascript
异步
JS 语言是单线程的
JS 需要异步的根本原因是 JS 是单线程运行的,即在同一时间只能做一件事,不能“一心二用”。
一个 Ajax 请求由于网络比较慢,请求需要 5 秒钟。 如果是同步,这 5 秒钟页面就卡死在这里啥也干不了了。 异步的话,就好很多了,5 秒等待就等待了,其他事情不耽误做,至于那 5 秒钟等待是网速太慢,不是因为 JS 的原因。
var a = true;
setTimeout(function () {
a = false;
}, 100);
while (a) {
console.log('while执行了');
}
以上代码的执行结果不是 100ms 后 a 为 false 所以打断 while 循环
事实上 当程序进入 while 循环后 就一直是死循环了
因为 JS 是单线程语言 所以无法执行到定时器
Set && Map
Set 和 Map 实例都不允许元素有重复
Set 的 key 和 value 一样 类似于数组
Map 的 key 和 value 可以设置 类似于对象
Set 实例的属性和方法有
size:获取元素数量。
add(value):添加元素,返回 Set 实例本身。
delete(value):删除元素,返回一个布尔值,表示删除是否成功。
has(value):返回一个布尔值,表示该值是否是 Set 实例的元素。
clear():清除所有元素,没有返回值。
Set 实例的遍历,可使用如下方法
keys():返回键名的遍历器。
values():返回键值的遍历器。不过由于 Set 结构没有键名,只有键值(或者说键名和键值是同一个值),
所以 keys()和 values()返回结果一致。
entries():返回键值对的遍历器。
forEach():使用回调函数遍历每个成员。
Map 实例的属性和方法如下:
size:获取成员的数量
set:设置成员 key 和 value
get:获取成员属性值
has:判断成员是否存在
delete:删除成员
clear:清空所有
Map 实例的遍历方法有:
keys():返回键名的遍历器。
values():返回键值的遍历器。
entries():返回所有成员的遍历器。
forEach():遍历 Map 的所有成员。
XMLHttpRequest
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = () => {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
alert(xhr.responseText);
}
}
};
xhr.open('GET', '/api', false);
xhr.send(null);
xhr.readyState 的状态码说明:
0 代理被创建,但尚未调用 open() 方法。
1 open() 方法已经被调用。
2 send() 方法已经被调用,并且头部和状态已经可获得。
3 下载中, responseText 属性已经包含部分数据。
4 下载操作已完成
xhr.status 即 HTTP 状态码,有 2xx 3xx 4xx 5xx 这几种,比较常用的有以下几种:
200 正常
3xx
301 永久重定向
302 临时重定向。临时的,不是永久的
304 资源找到但是不符合请求条件,不会返回任何主体。
如发送 GET 请求时,head 中有 If-Modified-Since: xxx(要求返回更新时间是 xxx 时间之后的资源),
如果此时服务器 端资源未更新,则会返回 304,即不符合要求
404 找不到资源
5xx 服务器端出错了
Fetch
更简洁的 ajax 并且支持 Promise 的回调
// 拿到一个本地json文件的内容
fetch('./demo.json')
.then((res) => res.json())
.then((res) => {
console.log(res);
});
闭包
函数 A 中有函数 B
函数 B 中使用了函数 A 的变量
函数 B 就被称为闭包
setTimeout
承接以上闭包的问题
用定时器的第三个问题可以解决一个老生常谈的问题
for (var i = 0; i < 10; i++) {
setTimeout(
(j) => {
console.log(j);
},
100,
i
);
}
// 打印 0 - 9
深拷贝
JSON.parse(JSON.stringify(obj))
会忽略 undefined
不能序列化函数
不能解决循环引用的对象
Object.assign({}, obj)
浅拷贝 只完成了属性的深拷贝
防抖 && 节流
call && apply && bind
bind 返回一个改变 this 的函数 强绑定 无法再修改内部 this 的指向
apply 立即执行该函数 接受一个参数数组
call 立即执行该函数 接受一个参数列表
事件的三个阶段
捕获 - 目标 - 冒泡
可以用 addEventListener 的第三个参数来决定是捕获还是冒泡
默认是 false 冒泡 改为 true 则为捕获
事件代理
思路:
如果是动态生成的元素 可以考虑在父元素上绑定事件
利用事件冒泡 在父元素处触发事件
跨域
JSONP
利用 script 标签不受跨域限制
仅限于 get 请求
document.domain
适用于二级域名相同的情况
如 a.chou.com && b.chou.com
Event Loop
执行顺序:
同步 > 微任务 > 宏任务
微任务
process.nextTick
Promise
Object.observe
MutationObserver
宏任务
script
setTimeout
setInterval
I/O
UI rendering
所以页面的 script 标签要写在页面的最下面 防止页面阻塞
浏览器渲染机制
处理 HTML 并构建 DOM 树
处理 CSS 并构建 CSSOM 树
将 DOM 树和 CSSOM 树合并成一棵渲染树
根据渲染树来布局 计算每一个节点的位置
调用 GPU 绘制 合成图层 显示在屏幕上
重绘 && 回流
重绘:不改变外观 只改变例如背景色 透明度等
回流:布局或几何属性需要改变
Last updated
Was this helpful?