1请描述event loop (事件循环/事件轮询)的机制,可画图)
js是单线程允许的
异步要基于回调来实现
event loop就是异步回调的实现原理
js的执行顺序
1 从前到后一行一行执行
2 如果某一行执行报错,停止下面代码的执行
3 先把同步的执行完,在执行异步
console.log('hi');
setTimeout(function cb1() {
console.log('cb1');
},5000)
console.log('byebye')
执行顺序
同步代码,一行一行放在call stack执行
遇到异步,先记录,等待时机执行(call stack为空) event loop开始工作(轮询查找 有放在call stack执行)
DOM 事件也使用回调 基于event loop
- 2什么是宏任务和微任务,两者有什么区别
-
3promise有哪三种变化 ,如何变化
三种状态 pending(待定)不会触发then和catch
resolved(成功)会触发后续then回调函数
rejected(失败)会触发后续catch回调函数 -
4 promise then 和catch的连接
//1
Promise.resolve().then(()=>{
console.log(1)
}).catch(()=>{
console.log(2)
}).then(()=>{
console.log(3)
})
结果 1 3
//2
Promise.resolve().then(()=>{
console.log(1)
throw new Error('error1')//有报错 所以整个then返回rejected的 所以执行.catch
}).catch(()=>{
console.log(2)
}).then(()=>{
console.log(3)
})
结果 1 2 3
//3
Promise.resolve().then(()=>{
console.log(1)
throw new Error('error1')
}).catch(()=>{
console.log(2) //执行catch没有报错 所以是resolved类型 执行then
}).catch(()=>{
console.log(3)
})
结果 1 2
- then正常返回resolved,里面有报错返回rejected
- catch正常返回resolved,里面有报错返回rejected
promise解决了什么问题?
-
回调地狱问题(异步函数的嵌套)
-
代码的可读性问题
-
1typeof能判断哪些类型?
2,async、await
promise then catch链式调用,但也是基于回调函数
async和await是同步的语法,彻底消灭回调函数(同步语法编写异步代码)
3 async、await和promise的关系
async、await是消灭异步回调的终极武器
执行async函数返回的promise对象
await相当于then
try catch可捕获异常,代替了promise的.catch
async function async (){
console.log('async1 start') //2
await async2()
console.log('async 1end')//5
}
async function async2 (){
console.log('async2')//3
}
console.log('start')//1
async1()
console.log(end)//4
是同步代码执行完,触发event loop 执行异步代码(await后面所有的东西最后执行 callback内容)
4宏任务和微任务
console.log(100)
setTimeout(()=>{ //异步先不执行
console.log(200)
})
promise.resolve().then(()=>{ //异步先不执行
console.log(300)
})
console.log(400)
100 400 300 200
为什么不先执行异步的200呢 ?
区别:
宏任务:settimeout,setinterval,ajax,dom事件 是DOM渲染后触发(如alert会阻断)
微任务:promise async/await (DOM渲染前触发)
微任务执行时机比宏任务要早 所以先执行的promise异步
直观现象就是用append添加标签元素,alert之后才去响应
5为何微任务执行更早
因为微任务是ES6语法规定的
宏任务是浏览器规定的
6手写Promise
const p = mypromise((resolve,reject)=>{
resolve(100)
})
p.then(data=>{
return data+2
}).catch(err=>console.error(err)
7原型和原型链
类型判断 instanceof 是谁构建的就为true
proto (隐式原型) prototype(显式原型)
每一个class都有一个prototype(显式原型),每一个new的实例对象都有proto (隐式原型) 指向class的显示原型prototype
获取属性 hx.name或执行方法时先从自身找,找不到自动去proto找
8闭包
//应用于闭包中的数据被隐藏,不被外界访问
函数作为参数被传递
const a = 100
function fn(){
console.log(a)
}
function print(fn){
const a = 200
fn()
}
print(fn)//100
函数作为返回值
function create(){
let a = 100
return function(){
console.log(a)
}
}
let num = create()
let a = 500
num() // 100
自由变量的查找,是在函数定义的地方向上查找,而不是执行的时候
9 this
this取什么样的值是在函数执行的时候确定的,而不是定义
call和bind都可以改变this指向,区别是bind会返回一个新的函数,需要接收
箭头函数的this取上级作用域的值
10同步和异步的区别是
遇到等待(网络请求),不能卡住,异步就是为了解决单线程
11手写promise加载一张图片
12前端使用异步的场景
如网络请求,ajax图片加载
定时任务 settimeout
13DOM操作
- DOM 的本质 html文件解析出来的一棵树
- DOM性能
避免频繁插入dom
如一次性生成10个具有文字的li
要创建一个文档片段,createDocumentFragment()
const list = document.getElementById('list');
//创建一个文档片段,此时还没有插入到dom结构中
const flag = document.createDocumentFragment()
for(let i=0;i<10;i++){
const li = document.createElement('li');
li.innerHTML = `list${i}`
frag.appendChild(li) //先插入文档片段中
}
list.appendChild(frag);//都完成之后在统一插入
- property和attribute的区别
property:修改对象属性,不会体现在html结构 childNodes、children、firstChild和一些点击事件如onclick和onblur等
attr|:修改html属性,改变html结构,.如style.width...
14 BOM操作
事件绑定 addEventListener('click',)
- 编写一个通用的事件监听哈数
- 描述事件冒泡的流程
- 无限下拉的图片列表,如何监听每个图片的点击
15手写ajax
const xhr = new XMLHttpRequest()
xhr.open("GET","/home",false)//异步是true
xhr.onreadtstatechange = function(){
if(xhr.readyState ===4){
if(xhr.status === 200){
alert(xhr.responseText)
}
}
}
xhr.send(null)
16跨域
ajax请求时,浏览器要求当前网页和服务器(server)必须同源(安全)
同源:协议,域名,端口三者必须一致
如前端:http://abc.com:8888 服务器:https://afgc.com/api/datra
加载图片 css js 可无视同源策略
所有的跨域都需要经过server端的允许和配合
如何解决跨域
JSONP
通过script来实现
<script>
window.callback = function(data){
console.log(data)
}
</script>
<script src='http://jfija/js> </script>
通过jQery来实现
$.ajax({
url:''
dataType:'jsonp',
jsonpCallback:'callback',
sucess:function(data){
console.log(data)
}
})
通过服务器设置cors http header
网友评论