異步、DOM、事件、頁面加載和優化面試題及知識點簡單總結

異步與單線程知識點:

什麼是異步(對比同步)

  • 同步:一行一行按順序依次執行代碼,當前代碼任務耗時執行會阻塞後續代碼的執行。這是一種典型的請求-響應模型,當請求調用一個函數或方法後,需等待其響應返回,而後執行後續代碼。
  • 異步:在等待當前任務的響應返回以前,能夠繼續執行後續代碼,即當前執行任務不會阻塞後續執行。異步編程,不一樣於同步編程的請求-響應模式,其是一種事件驅動編程,請求調用函數或方法後,無需當即等待響應,能夠繼續執行其餘任務,而以前任務響應返回後能夠經過狀態、通知和回調來通知調用者。

單線程

  • 一個瀏覽器進程中只有一個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就放在後面javascript

DOM BOM知識點

DOM節點操做

DOM節點本質上是可識別,可操做的js對象css

  • 獲取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.heighthtml

  • location
    location.href

location.protocol //http https
location.host
location.pathname
location.search
location.hashjava

  • history
    history.back()

history.forWard()node

面試題

  • DOM操做經常使用api
    獲取DOM節點 節點的property attribute

獲取父,子節點
新增 刪除節點webpack

  • DOM節點的attr和property區別
    property是一個js對象的屬性

attribute是html標籤的屬性web

  • 檢測瀏覽器類型
    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標籤彈出相應的內容ajax

<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狀態碼
  1. 未初始化 尚未調用send()方法

1 載入 已經調用send()方法 正在發送請求
2 載入完成 send()方法執行完成 已經接收到所有響應內容
3 交互 正在解析響應內容
4 完成 響應內容解析完成 能夠在客戶端調用編程

  • status狀態碼
  1. 請求成功

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)
  • 跨域方法
  1. 服務器端設置http header
  • 請描述一下cookie,sessionStorage,和localStorage的區別
    容量區別,cookie爲4k,localStorage和sessionStorage爲5M

cookie每次請求都會被攜帶在ajax中,local Storage和session Storage不會被攜帶只做爲存儲使用

  • window.onload 和 DOMContentLoaded區別
    前者在頁面所有資源加載完纔會執行 包括圖片視頻等

後者在dom渲染玩便可執行 此時圖片視頻還未加載完

相關文章
相關標籤/搜索