3

异步与单线程知识点:

什么是异步(对比同步)

  • 同步:一行一行按顺序依次执行代码,当前代码任务耗时执行会阻塞后续代码的执行。这是一种典型的请求-响应模型,当请求调用一个函数或方法后,需等待其响应返回,然后执行后续代码。
  • 异步:在等待当前任务的响应返回之前,可以继续执行后续代码,即当前执行任务不会阻塞后续执行。异步编程,不同于同步编程的请求-响应模式,其是一种事件驱动编程,请求调用函数或方法后,无需立即等待响应,可以继续执行其他任务,而之前任务响应返回后可以通过状态、通知和回调来通知调用者。

单线程

  • 一个浏览器进程中只有一个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状态码
  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渲染玩即可执行 此时图片视频还未加载完


imgwho
78 声望7 粉丝

undefined