异步与单线程知识点:
什么是异步(对比同步)
- 同步:一行一行按顺序依次执行代码,当前代码任务耗时执行会阻塞后续代码的执行。这是一种典型的请求-响应模型,当请求调用一个函数或方法后,需等待其响应返回,然后执行后续代码。
- 异步:在等待当前任务的响应返回之前,可以继续执行后续代码,即当前执行任务不会阻塞后续执行。异步编程,不同于同步编程的请求-响应模式,其是一种事件驱动编程,请求调用函数或方法后,无需立即等待响应,可以继续执行其他任务,而之前任务响应返回后可以通过状态、通知和回调来通知调用者。
单线程
- 一个浏览器进程中只有一个JS的执行线程,同一时刻内只会有一段代码在执行
异步使用场景
- 定时任务: setTimeout setInterval
- 网络请求: ajax 动态
<img>
加载 - 事件绑定
//单线程就是一次只能做一件事
//异步:不会阻塞
console.log(100)
setTimeout(function (){
console.log(200)
},1000)
console.log(300)
//打印100 300 1秒后打印200
//同步:会阻塞
console.log(100)
alert(299) //程序会卡在这里
console.log(300)
//ajax示例
console.log('start')
$.get('./data.json', function (data) {
console.log(data)
})
console.log('end')
//先打印start 再打印end 最后get请求完成后打印data
//<img>加载示例
console.log('start')
var img = document.createElement('img')
img.onload = function () {
console.log('loaded')
}
img.src = '/xx.jpg'
console.log('end')
//start ==> end ==> img.src = '/xx.jpg' ==>loaded
//事件绑定示例
console.log('start')
document.getElementById('btn1').addEventListener('click', function () {
alert('clicked')
})
console.log('end')
//start ==> end ==> alert('clicked')
面试题
- 同步异步的区别
同步会阻塞代码执行,异步不会(如alert是同步 setTimeout是异步) - setTimeout题目
console.log(1)
setTimeout(function () {
console.log(2)
}, 0)
console.log(3)
setTimeout(function () {
console.log(4)
}, 1000)
console.log(5)
1 3 5 2 一秒后4 遇到setTimeout就放在后面
DOM BOM知识点
DOM节点操作
DOM节点本质上是可识别,可操作的js对象
- 获取DOM节点
var div = document.getElementById('div')//元素
var divList = document.getElementByTagName('div')//集合
console.log(divList.length)
console.log(divList[0])
var div = document.getElementByClassName('div')//元素
var pList = document.querySelectorAll('p')//集合
- Property js对象属性
var pList = document.querySelectorAll('p)
var p = pList[0]
console.log(p.style.width) //获取样式
p.style.width = '100px' //修改样式
console.log(p.classNmae) //获取class
p.className = 'p1' //修改class
//获取nodeName和nodeType
console.log(p.nodeName)
console.log(p.nodeType)
- Attribute html标签
var pList = document.querySelectorAll('p')
var p = pList[0]
p.getAttribute('data')
p.setAttribute('data', 'data-json')
p.getAttribute('style')
p.setAttribute('style', 'font-size: 30px')
DOM结构操作
- 新增节点
- 获取父,子节点
- 删除节点
BOM操作
- navigator
var ua = navigator.userAgent
var isChrome = ua.indexOf('Chrome')
console.log(isChrome)
- screen
screen.width
screen.height
- location
location.href
location.protocol //http https
location.host
location.pathname
location.search
location.hash
- history
history.back()
history.forWard()
面试题
- DOM操作常用api
获取DOM节点 节点的property attribute
获取父,子节点
新增 删除节点
- DOM节点的attr和property区别
property是一个js对象的属性
attribute是html标签的属性
- 检测浏览器类型
navigator.userAgent
事件知识点
通用事件绑定
//标准方法
var btn = document.getElementById('btn1')
btn.addEventListener('click', function (event) {
console.log('clicked')
})
//封装事件
function bindEvent(elem, type, fn) {
elem.addEventListener(type, fn)
}
var a = document.getElementById('link')
bindEvent(a, 'click', function(e) {
e.preventDefault() //阻止默认行为
alert('clicked')
})
事件冒泡
点击p1 alert激活 若没有e.preventDefault,事件将继续向上冒泡直到找到body中的alert取消
<div id="div1">
<p id="p1">激活</p>
<p id="p2">取消</p>
<p id="p3">取消</p>
<p id="p4">取消</p>
</div>
<div id="div2">
<p id="p5">取消</p>
<p id="p6">取消</p>
</div>
<script type="text/javascript">
function myBindEvent(elem, type, fn) {
elem.addEventListener(type, fn)
}
var p1 = document.getElementById('p1')
var body = document.body
myBindEvent(p1, 'click', function (e) {
e.stopPropagation() //阻止冒泡
alert('激活')
})
myBindEvent(body, 'click', function (e) {
alert('取消')
})
</script>
事件代理
点击每个a标签弹出相应的内容
<div id="div1">
<a href="#">a1</a>
<a href="#">a2</a>
<a href="#">a3</a>
<a href="#">a4</a>
<!-- 会随时新增更多a标签 -->
</div>
<script type="text/javascript">
function myBindEvent(elem, type, fn) {
elem.addEventListener(type, fn)
}
var div1 = document.getElementById('div1')
myBindEvent(div1, 'click', function (e) {
var target = e.target //获取要绑定事件的元素
if (target.nodeName === 'A') {
alert(target.innerHTML)
}
})
</script>
面试
- 编写一个通用的事件监听函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>通用事件监听函数</title>
</head>
<body>
<div id="div1">
<a href="http://baidu.com" id="link1">baidu</a>
<a href="http://baidu.com" id="link2">baidu</a>
<a href="http://baidu.com" id="link3">baidu</a>
<a href="http://baidu.com" id="link4">baidu</a>
<p id="p1">激活</p>
<p id="p2">取消</p>
</div>
<div id="div2">
<p id="p3">取消</p>
<p id="p4">取消</p>
</div>
<script>
function bindEvent(elem, type, selector, fn) {
if (fn == null) {
fn = selector
selector = null
}
elem.addEventListener(type, function (e) {
var target
if (selector) {
//是代理的时候
target = e.target
if (target.matches(selector)) {
fn.call(target, e)
}
} else {
fn(e) //不是代理的时候
}
})
}
//使用代理
var div1 = document.getElementById('div1')
bindEvent(div1, 'click', 'a', function (e) {
e.preventDefault()
console.log(this.href)
})
//不使用代理
var p1 = document.getElementById('p1')
bindEvent(p1, 'click', function (e) {
console.log(p1.innerHTML)
})
</script>
</body>
</html>
- 事件冒泡过程
DOM树形结构 事件冒泡 阻止冒泡 - 对于一个无限下拉加载图片的页面,如何给每个图片绑定事件
事件代理
ajax知识点
- XMLHttpRequest
- readyState状态码
- 未初始化 还没有调用send()方法
1 载入 已经调用send()方法 正在发送请求
2 载入完成 send()方法执行完成 已经接收到全部响应内容
3 交互 正在解析响应内容
4 完成 响应内容解析完成 可以在客户端调用
- status状态码
- 请求成功
3xx 需要重定向 浏览器直接跳转
4xx 客户端请求错误
5xx 服务器端错误
- 跨域
浏览器的同源策略不允许ajax访问其他域的接口
协议(http)、域名(baidu.com)、端口(80)有一个不同就算跨域
可以跨域的三个标签 img script link
jsonp:利用src属性引入其他域下的js,需要后端返回数据是一个函数调用,处理后的数据作为函数的参数传入,实现跨域访问接口。
服务器端设置http header:
//注意:不同后端语言的写法可能不一样
//第二个参数填写允许跨域的域名称,不建议直接写"*"
response.setHeader('Access-Control-Allow-Origin','http://a.com,http://b.com');
response.setHeader('Access-Control-Allow-Headers','X-Request-With');
response.setHeader('Access-Control-Allow-Methods','PUT,POST,GET,DELETE,OPTIONS');
//接受跨域的cookie
response.setHeader('Access-Control-Allow-Credentials','true');
页面加载知识点
- 加载资源形式:
输入url 加载html,加载html中的静态资源 script link img - 加载资源过程
浏览器根据dns服务器得到域名的ip地址
向这个地址发送http请求
服务器收到,处理,返回请求
浏览器得到返回内容
- 浏览器渲染页面过程
根据 HTML 结构生成 DOM Tree
根据css生成css节点
将dom和css节点整合成渲染树
根据渲染树开始渲染和展示
遇到script标签时会阻塞渲染
性能优化知识点
webpack打包、使用cdn、服务端渲染ssr、图片懒加载、事件节流、事件代理
面试题
- 手写ajax
var xhr = XMLHttpRequest()
xhr.open("GET","/api", false)
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.readyState == 200) {
console.log(xhr.responseText)
}
}
}
xhr.send(null)
- 跨域方法
- 服务器端设置http header
- 请描述一下cookie,sessionStorage,和localStorage的区别
容量区别,cookie为4k,localStorage和sessionStorage为5M
cookie每次请求都会被携带在ajax中,local Storage和session Storage不会被携带只作为存储使用
- window.onload 和 DOMContentLoaded区别
前者在页面全部资源加载完才会执行 包括图片视频等
后者在dom渲染玩即可执行 此时图片视频还未加载完