JavaScript面试题

2023-07-28  本文已影响0人  扶光_

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


//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

promise解决了什么问题?

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操作

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);//都完成之后在统一插入

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

上一篇 下一篇

猜你喜欢

热点阅读