前端面试知识点梳理——JS-Web-API

315 阅读5分钟

从JS基础知识到JS Web API

  • JS基础知识,规定语法(ECMA 262标准)
  • JS Web API,网页操作的API(W3C标准)
  • 前者是后者的基础,两者结合才能真正实际应用    

JS Web API

  • DOM
  • BOM
  • 事件绑定
  • Ajax
  • 存储

JS-Web-API-DOM

前言

  • Vue 和 React框架应用广泛,封装了DOM操作
  • 但 DOM 操作一直都会是前端工程师的基础,必备知识
  • 只会Vue而不懂DOM操作的前端程序员,不会长久

DOM(Document Object Model)

DOM本质

  • DOM本质是HTML语言在浏览器中解析出来的树形结构

DOM节点操作

  • 获取DOM节点
    • getElementById
      const div1 = document.getElementById('div1')  // 返回元素
      
    • getElementsByTagName
      const divList = document.getElementsByTagName('div')  // 返回集合
      
    • getElementsByClassName
      const divList = document.getElementsByClassName('.container')  // 返回集合
      
    • querySelectorAll
      const divList = document.querySelectorAll('p')  // 返回集合
      
  • DOM 节点的property 和 attribute 区别
    • property
      const p = document.querySeletorAll('p')[0]
      p.style.width = '100px'
      
    • attribute
      const p = document.querySeletorAll('p')[0]
      p.setAttribute('data-name','wchao')
      p.getAttribute('data-name')
      
    • 两者区别
      <-- 以此dom为例子 -->
      <input id='test' class='a b c' type='text' value="1234" />
      
      • 体系不同:二者是属于两套系统的不同的东西,但其中的属性又有所重合,且attributes本身又是property中的一个属性。所以attribute的属性一般都可以通过property 的方式获取到。
      • 来源不同:在Js 的世界中,对象是通过构造函数创建的,所以每个对象中都天生自带了许多属性(property), 而attribute则是我们在书写代码时设置的一些属性。
      • 状态不同:状态这个描述可能不太准确,attribute是我们给这个标签设置的属性,类似于这个标签的默认或初始属性值;而property 是这个dom对象或标签现在的属性。以这个input为例,我们设置的初始value值为“1234”,若我们输入了其他值如:“abcd”,此时property: input.value  的值为“abcd”, attribute:input.attributes.value 的值仍为 "1234"。当然不是所以的属性是这样,比如 id, class,type等属性是始终保持一致的。
    • 建议:尽量用 property 操作,因为property可能会在JS机制中,避免一些不必要的DOM渲染;但是attribute是修改HTML结构,一定会引起DOM结构的重新渲染,而DOM重新渲染是比较耗费性能的

DOM结构操作

  • 新增/插入节点
    // 新增
    document.createElement(eName);  //创建一个节点
    // 插入
    parentNode.appendChild(newNode);        //给某个节点添加子节点
  • 获取子元素列表,获取父元素
    // 获取父元素
    p1.parentNode
    // 获取子元素列表
    // 需要判断元素节点的节点类型(nodeType)
    const children = [].slice .call(box.childNodes).filter((ele) => ele.nodeType === 1)
    console.log(children)
  • 删除子节点
    // 删除
    parentNode.removeChild(node);  //删除某个节点的子节点 node是要删除的节点

DOM性能

  • DOM操作非常“昂贵”,避免频繁的DOM操作
  • 对DOM查询做缓存
// 不缓存 DOM 查询结果
for(let i = 0; i<document.getElementsByTagName('p').length; i++){
    //每次循环,都会计算length,频繁进行 DOM 查询
}
// 缓存 DOM 查询结果
const pList = document.getElementByTagName('p')
const length = pList.length
for(let i = 0; i < length; i++){
    //缓存length,只进行一次DOM查询
}
  • 将频繁操作改为一次操作(createDocumentFragment)
// 频繁操作
const list = document.getElementById('list')
for(let i = 0; i < 10; i++){
    const li = document.createElement('li')
    li.innerHTML = `List item ${i}`
    list.appendChild(li)
}
// 优化
const list = document.getElementById('list')
const frag = document.creatDocumentFragment();
for(let i = 0; i < 10; i++){
    const li = document.createElement('li')
    li.innerHTML = `List item ${i}`
    frag.appendChild(li)
}
list.appendChild(frag)

JS-Web-API-BOM

BOM(Browser Object Model)

navigator(浏览器的信息)

  • 判断ua navigator.userAgent(各个浏览器,为了兼容限制的网页,添加了很多别的浏览器的标识在其中,所以很难明显的判断浏览器是谁的浏览器。只能网上查找,他们各自的检测方案)
const ua = navigator.userAgent
console.log(ua)  //"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.164 Safari/537.36"
const isChorme = ua.indexOf('Chorme')
console.log(isChorme)

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()  // 浏览器前进
history.go()       // 浏览器跳转

JS-Web-API-事件

事件绑定

  • 语法
    target.addEventListener(type, listener, options);
    
  • 手写通用事件绑定
function bindEvent(elem,type,fn){
    elem.addEventListener(type,fn)
}



const btn1 = document.getElementById('btn1')
bindEvent(btn1,'click',event=>{
    event.preventDefault()
    console.log('click')
})

事件冒泡

  • 概念
    在一个对象上触发某类事件,这个事件会向这个对象的的父级传播,从里到外,直至它被处理或者到达了对象层次的最顶层,即document对象。这个过程就是JavaScript的事件冒泡。
    <div id="div1">
        <div id="div2"></div>
     </div>
     <script>
         var div1 = document.getElementById("div1");
         var div2 = document.getElementById("div2");
         div2.onclick = function(){
             alert(1);
         };
         div1.onclick = function(){
             alert(2);
         };//父亲
     </script>
    
  • 阻止冒泡
    event.stopPropagation
    

事件代理

  • 事件代理(Event Delegation),又称之为事件委托。是 JavaScript 中常用绑定事件的常用技巧。顾名思义,“事件代理”即是把原本需要绑定的事件委托给父元素,让父元素担当事件监听的职务。事件代理的原理是DOM元素的事件冒泡。使用事件代理的好处是可以提高性能
  • 可以大量节省内存占用,减少事件注册,比如在table上代理所有td的click事件就非常棒
  • 可以实现当新增子对象时无需再次对其绑定
  • 基于事件代理的通用绑定方法
    function bindEvent(elem,type,selector,fn){
        if(fn == null){
            fn = selector
            selector = null
        }
        elem.addEventListener(type,event=>{
            const target = event.target
            if(selector){
                // 代理绑定
                if(target.matches(selector)){
                    fn.call(target,event)
                }
            }else{
                // 普通绑定 
                fn.call(target,event)
            }
        })
    }
    var ul = document.getElementById("ul");
    bindEvent(ul,'click','li',event => {
        console.log(li click)
    })
    

JS-Web-API-Ajax

XMLHttpRequest

  • 什么是XMLHttpRequest XMLHttpRequest(XHR)对象用于与服务器交互。通过 XMLHttpRequest 可以在不刷新页面的情况下请求特定 URL,获取数据。这允许网页在不影响用户操作的情况下,更新页面的局部内容。XMLHttpRequest 在 AJAX编程中被大量使用。
  • 手写原生ajax(get请求)
const xhr = new XMLHttpRequest()
xhr.open('GET','./data/test.json',false)
xhr.onreadystatechange=functon(){
    if(xhr,readyState == 4){
        if(xhr.status==200){
            alert(xhr.responseText)
        }
    }
}
xhr.send(null)
  • 手写原生ajax(post请求)
const xhr = new XMLHttpRequest()
xhr.open('POST','./data/test.json',true)
xhr.onreadystatechange=functon(){
    if(xhr,readyState === 4){
        if(xhr.status === 200){
            alert(xhr.responseText)
        }
    }
}
const postData = {
    userName:'zhangsan',
    password:'xxx'
}
xhr.send(JSON.stringify(postData))
  • xhr.readuState 状态
    • 0:未初始化,还未调用send方法
    • 1:载入,已调用send方法,正发送请求
    • 2:载入完成,send方法执行完毕,已接收到全部响应内容
    • 3:交互,正在解析响应内容
    • 4:完成,响应内容解析完成,可以再客户端调用
  • xhr.status 状态
    • 2xx 表示成功处理请求,如200
    • 3xx 需要重定向,浏览器直接跳转,如301 302 304
    • 4xx 客户端请求错误,如404 403
    • 5xx 服务器端错误,如500

跨域

  • 什么是跨域(同源策略)
  • 同源策略
    • ajax请求时,浏览器要去当前网页和server必须同源(安全)
    • 同源:协议、域名、端口,三者必须一致
    • 加载图片、css 、js 可无视同源策略
    • 举例
      前端:a.com:8080/
      sever: b.com/api/xx
  • 常见跨域方法
    • 同源策略(利用img标签,可用于统计打点,可使用第三方统计服务)
    • JSONP —— 需要与服务端配合(只支持get请求)
    • CORS ——服务器设置 http header * (支持所有类型请求)
    • postMessage
    • websocket
    • Node js中间件代理
    • nginx反向代理

JS-Web-API-存储

cookie

  • 语法:document.cookie = newCookie;
  • 本身用于浏览器和server通讯
  • 最早是被“借用”到本地存储
  • 缺点
    • 1.存储大小,最大4kb
    • 2.http 请求时需要发送到服务端,增加请求数据量
    • 3.只能用 document.cookie = '...' 来修改,太过简陋

localStorage 和 sessionStorage

  • HTML5 专门为存储设计,大小为5M
  • Api简单易用(setItem,getItem)
  • 不会随着http请求被发送出去
  • 二者区别
    • localStorage 永久存储,除非代码或手动删除
    • sessionStorage 数据只存在于当前会话,浏览器关闭则清空
    • 一般用 localStorage 会更多一点