JavaScript高级

简介: DOM是文档对象模型,将HTML解析为树形结构,供JavaScript操作。包含节点增删改查、事件绑定、BOM与Ajax等核心API,实现动态网页交互。

2.1 DOM操作
2.1.1 到底什么是DOM?
DOM的全称是文档对象模型Document Object Model,它在本质上是一种文档平台。DOM是W3C DOM工作组提倡的一种接口规范,它是独立于访问、解析或更新XML数据机制的一种应用。通俗地说,DOM是方便开发人员对XML文档进行操作的分层模型。有足够清楚的层次模型,才会得到足够灵活的数据操作。

    在网页上,组成页面(或文档)的对象被组织在一个树型结构中。JavaScript将文档树中的每一项都当作对象,可以使用JavaScript操纵这些对象。用来表示文档中对象的标准模型就称为DOM

    树中的每个对象也称为树的节点(node)。如果节点包含HTML标签,那么它就称为元素节点;否则,称为文本节点,元素节点可以包含文本节点。

2.1.2 DOM操作的常用API有哪些?
节点查找API
document.getElementById :根据ID查找元素,大小写敏感,如果有多个结果,只返回第一个;
document.getElementsByClassName :根据类名查找元素,多个类名用空格分隔,返回一个 HTMLCollection 。注意兼容性为IE9+(含)。另外,不仅仅是document,其它元素也支持 getElementsByClassName 方法;
document.getElementsByTagName :根据标签查找元素, * 表示查询所有标签,返回一个 HTMLCollection 。
document.getElementsByName :根据元素的name属性查找,返回一个 NodeList 。
document.querySelector :返回单个Node,IE8+(含),如果匹配到多个结果,只返回第一个。
document.querySelectorAll :返回一个 NodeList ,IE8+(含)。
document.forms :获取当前页面所有form,返回一个 HTMLCollection ;
节点创建API
createElement创建元素
createTextNode创建文本节点
cloneNode 克隆一个节点
createDocumentFragment
节点修改API
appendChild
insertBefore
insertAdjacentHTML
Element.insertAdjacentElement()
removeChild
replaceChild
节点关系API
1、父关系API
parentNode :每个节点都有一个parentNode属性,它表示元素的父节点。Element的父节点可能是Element,Document或DocumentFragment; parentElement :返回元素的父元素节点,与parentNode的区别在于,其父节点必须是一个Element元素,如果不是,则返回null;
2、子关系API
children :返回一个实时的 HTMLCollection ,子节点都是Element,IE9以下浏览器不支持;
childNodes :返回一个实时的 NodeList ,表示元素的子节点列表,注意子节点可能包含文本节点、注释节点等;
firstChild :返回第一个子节点,不存在返回null,与之相对应的还有一个 firstElementChild ;
lastChild :返回最后一个子节点,不存在返回null,与之相对应的还有一个 lastElementChild ;
3、兄弟关系型API
previousSibling :节点的前一个节点,如果不存在则返回null。注意有可能拿到的节点是文本节点或注释节点,与预期的不符,要进行处理一下。
nextSibling :节点的后一个节点,如果不存在则返回null。注意有可能拿到的节点是文本节点,与预期的不符,要进行处理一下。
previousElementSibling :返回前一个元素节点,前一个节点必须是Element,注意IE9以下浏览器不支持。
nextElementSibling :返回后一个元素节点,后一个节点必须是Element,注意IE9以下浏览器不支持。
元素属性型API
1、setAttribute 给元素设置属性: 2、getAttribute 3、hasAttribute
样式操作API(面试考点)
1、直接修改元素的样式

elem.style.color = 'red';  
elem.style.setProperty('font-size', '16px');  
elem.style.removeProperty('color');

2、动态添加样式规则

var style = document.createElement('style');  
style.innerHTML = 'body{color:red} #top:hover{background-color: red;color: white;}';  
document.head.appendChild(style);
Copy

3、classList获取样式属性
Note
了解dom节点样式(classList)的remove, add, toggle, contains, replace等方法的使用。
4、window.getComputedStyle 通过 element.sytle.xxx 只能获取到内联样式,借助 window.getComputedStyle 可以获取应用到元素上的所有样式,IE8或更低版本不支持此方法。

var style = window.getComputedStyle(element[, pseudoElt]);

2.1.3 DOM节点的attr和proerty的区别

// proprty------>>>获取nodeName和nodeType(property实际上就是JS对象的一个属性)如:text : 3(#text), p : 1(p)
    console.log(pList[0].nodeName);         // p
    console.log(pList[0].nodeType);         // 1
// attribute------>>> 获取一个HTML标签的属性信息(设置和修改)
    var a = document.getElementsByTagName('a')[0];
    console.log(a.getAttribute('data-origin'));
    console.log(a.getAttribute("href_name"));           // 可以给一个HTML标签设置任意的属性名称,无论这个属性内部是否存在
a.    setAttribute('sex', 'male')
// 区别:
// (JS对象&HTML标签)property实际上是一个普通JS对象本身的基本属性,但是attribute实际上是一个HTML标签上面的属性信息

Note
区别:(JS对象&HTML标签)property实际上是一个普通JS对象本身的基本属性,但是attribute实际上是一个HTML标签上面的属性信息
2.2 BOM操作
2.2.1 如何检测浏览器的类型?

var ua = navigator.userAgent;
    var isChrome = ua.indexOf('Chrome');
    console.log('is Chrome?', isChrome > 0, navigator.userAgent);
    console.log('电脑屏幕大小:', screen.width, screen.height)

2.2.2 如何拆解URL的各个部分?

// location
    console.log(location.href);                 // 完整的url地址,http://localhost:8080/JS-Professional/begin/02-%E5%9F%BA%E7%A1%80%E8%BF%9B%E9%98%B6/01-%E4%BB%8E%E5%9F%BA%E7%A1%80%E5%88%B0%E8%BF%9B%E9%98%B6.html?_ijt=i8ctmkc87dvh03tdaf51rn5v1i
    console.log(location.protocol)              // http/https
    console.log(location.host, location.hostname)                  // www.52tech.tech
    console.log(location.pathname);             // host之后的全部内容,JS-Professional/begin/02-%E5%9F%BA%E7%A1%80%E8%BF%9B%E9%98%B6/01-%E4%BB%8E%E5%9F%BA%E7%A1%80%E5%88%B0%E8%BF%9B%E9%98%B6.html
    console.log(location.search);               // search就是?之后的全部内容,?_ijt=i8ctmkc87dvh03tdaf51rn5v1i(包括?)
    console.log(location.hash);                 // #后面的内容(包括#)

2.3 事件操作
2.3.1 编写一个通用的事件监听函数

function bindEvent(ele, type, selector, fn){
   
        if (fn == null) {
   
            fn = selector;
            selector = null;
        }

        // addEventListener 的最后一个参数默认是false, 表示的是事件冒泡,自下向上去捕获事件,true:表示事件捕获,表示事件自外向里的方式
        ele.addEventListener(type, function(e){
   
            if (selector) {
   
                // 使用的是代理的方式的话
                if (e.target.matches(selector)){
               // 这里需要去判断当前点击的那个对象是不是我点击的那个对象
                    fn.call(e.target, e);
                }
            } else {
   
                // 不使用代理的话
                fn(e);
            }
        });
    }


    // 这里表示对这个div1 内部的所有的a标签使用事件冒泡
    bindEvent(document.getElementById('div4'), 'click', 'p', function (e) {
   
        console.log(this.innerHTML + 'hahaah')
    })
版本2/**
     * 实现一个通用的事件绑定函数(代码简洁,减少了浏览器的占用)
     * @param element
     * @param type
     * @param selector
     * @param fn
     */
    function bindEvent(element, type, selector, fn) {
   
        // if (fn === null || fn === undefined)        // 这里可以直接优化为fn == null
        if (fn == null){
   
            // 只有3个参数的话
            fn = selector;
            selector = null;
        }

        element.addEventListener(type, function (e) {
   
            var target;
            // 如果selector有的话,说明此事element就是一个代理
            if (selector) {
   
                target = e.target;
                // 如果当前的target满足这个选择器的话
                // 如果元素被指定的选择器字符串选择,Element.matches()  方法返回true; 否则返回false。
                // document.getElementById('div1').matches('div')    true
                // matches里面的参数实际上是一个HTML标签:a, p, div …………, 内容也是不区分大小写的,有点类似于nodeName 或者nodeType 这样的判断
                if (target.matches(selector)){
   
                    // 修改this的指向
                    fn.call(target, e);
                }
            }else {
   
                fn(e);
            }
        });
    }

2.3.2 描述事件冒泡的流程
Note
"DOM2级事件”规定的事件流包含三个阶段:事件捕获阶段,处于目标阶段和事件冒泡阶段。首先发生的是事件捕获,然后是实际的目标接收到事件,最后阶段是冒泡阶段。
事件冒泡: 按照DOM树形结构向上冒泡(p --- >>> div --- >>> body --- >>> document),
事件捕获 (document—>—>—>的顺序进行传播的)
2.3.3 对于一个无线下拉图片的页面,如何给每一个图片绑定一个事件

// 代理(div3里面的所有a标签都需要进行事件的监听)
    var div3 = document.getElementById('div3');
    bindEvent(div3, 'click', function (e) {
   
        e.preventDefault();
        e.stopPropagation()
        // 可以获取真实触发的那个元素
        var target = e.target;
        console.log(target.nodeName, target.nodeType);      // 每一种页面标签实际上都有一个自己专属的nodeName
        // 这里的目的主要是用于过滤,只处理a标签的事件处理
        if ('A' === target.nodeName) {
   
            //  如果当前点击的a标签就是自己
            alert(target.innerHTML)
        }
    })

2.4 Ajax操作
2.4.1 手动编写一个ajax,不依赖第三方库
2.4.2 跨域的几种实现方式以及底层的实现原理
服务器端的使用:response.setHeader(Access-Control-Allow-Origin, "http://www.baidu.com, http://www.52tech.tech")允许跨域
使用JSONP
2.4.3 JSONP的实现原理
Note
跨域:浏览器有同源策略,不允许ajax访问其他域接口
跨域条件:协议、域名、端口,有一个不同就是跨域
可以跨域加载资源的3个标签:

<img src="">, <link href="">, <script src="">

img用途:主要用于打点统计,统计网站可能是其他域
link, script用途:可以使用CDN,可以使用其他域
script用途:可以用于JSONP
2.4.3.1 跨域注意事项:
所有的跨域请求都必须经过信息提供方的允许才可以获取
如果未经允许就可以直接获取,就是浏览器的同源策略出现漏洞
2.4.3.2 浏览器端实现(提前定义一个回调函数)

//封装一个jsonp请求的函数
  function query(opt) {
   
      let str = ""
      for (let key in opt) {
   
          str += key + "=" + opt[key] + "&"
      }
      return str
  }
  //设置默认回调函数的名字
  const defaultOptions = {
   
      callbackName: "callback"
  }
  function jsonp(url, opt, options = defaultOptions) {
   
      //参数解析  URL为访问的接口 opt为传播的数据  option 为接受参数的回调函数
      return new Promise((resolve, reject) => {
   
          //判断下这个?是不是存在
          let index = url.indexOf("?");
          url += index != -1 ? query(opt) : "?" + query(opt);
          url = url + `${
     options.callbackName}=${
     options.callbackName}`;
          //首先创造一个标签 带有src的
          const scriptDom = document.createElement("script");
          //设置其src属性
          scriptDom.setAttribute("src", url);
          //在window系统上创建一个回调函数用来接受数据
          window[options.callbackName] = (res) => {
   
              //在接受到了参数动态删除这个script节点和window上面的方法
              delete window[options.callbackName];
              document.body.removeChild(scriptDom)
              //接受成功后调用resolve
              if (res) {
   
                  resolve(res)
              } else {
   
                  reject("服务器暂没有获取到数据")
              }
          }
          //动态创建script标记,错误的监听
          scriptDom.addEventListener('error', () => {
   
              delete window['jsonpCallback'];
              document.body.removeChild(script);
              reject('服务器加载失败!');
          });
          document.body.append(scriptDom)
      })
  }

2.4.3.3 后端实现

const url = require("url")

router.get("/api", (req, res, next) => {
   
  //将script标签的src的URL请求转成对象
  const opj = url.parse(req.url, true).query;
  //然后原理就是调用这个回调函数来进行传参
  let {
   
    callback
  } = opj;
  //如果这个回调函数存在证明是jsonp请求
  if (callback) {
   
    let resault = JSON.stringify({
   
      code: 1,
      msg: "express框架传回去的参数"
    });
    res.send(`${
     callback}(${
     resault})`)
  }
})

2.5 本地存储
2.5.1 cookie, sessionStorage, localStorage 的区别
Cookie
存储量,只有4kb
所有的http请求都会带有cookie,会直接影响获取资源效率
API,document.cookie
localstorage
localstorage.setItem(key, value);localstorage.getItem('key');
存储量5MB
sessionStorage:会话级别
Warning
【坑】IOS safari的隐藏模式下,使用localStorage.getItem('key') 会报错,建议使用try{}catch(e){} 来实现可以防止报错

相关文章
|
2月前
|
并行计算 API Python
Python 3.12 隐藏利器:用子解释器实现真正并行
Python 3.12 隐藏利器:用子解释器实现真正并行
233 134
|
2月前
|
缓存 监控 开发工具
用 Python 的 LRU Cache 优化函数性能
用 Python 的 LRU Cache 优化函数性能
260 143
|
2月前
|
机器学习/深度学习 人工智能 算法
基于 YOLOv8 的智能杂草检测识别实战 [目标检测完整源码]
基于YOLOv8的智能杂草检测系统,融合目标检测与PyQt5可视化,实现田间杂草精准识别。涵盖数据标注、模型训练、推理部署全流程,支持图片、视频及实时摄像头检测,具备高精度、强鲁棒性与工程落地价值,适用于智慧农业、科研教学等场景,提供完整源码与预训练模型,助力AI+农业应用开发。
149 3
基于 YOLOv8 的智能杂草检测识别实战 [目标检测完整源码]
|
2月前
|
人工智能 自然语言处理 调度
面向AI原生时代的架构思考:基于统一适配层与知识图谱的GEO优化系统设计
当AI成为用户获取信息的入口,企业需重构内容战略。传统SEO失效,GEO(生成式引擎优化)应运而生——通过统一适配层与行业知识图谱双引擎,打通多平台协议壁垒,实现专业内容的结构化、可读化与智能分发,构建AI时代的增长新基座。(238字)
207 7
|
2月前
|
人工智能 运维 程序员
2026年8个适合程序员逛的在线社区
这是一个开源与共享的时代,编程学习离不开优质社区。GitHub汇聚全球优秀代码,Stack Overflow解决技术难题,InfoQ洞察前沿趋势,CSDN、博客园、51CTO等中文平台助力本土开发者成长。无论是源码学习、问题答疑还是技术交流,这些社区都为程序员提供了丰富资源与成长空间,是提升技能的必备利器。
|
2月前
|
机器学习/深度学习 人工智能 自然语言处理
下载了个AI模型怎么这么多文件?解密HuggingFace的神秘清单
你有没有遇过这种情况:满心欢喜下载了个7GB的AI模型,结果发现里面有11个不同的文件,完全不知道哪个是干什么的?就像买了个宜家家具,零件一大堆,说明书看不懂一样!其实每个文件都有它的使命,掌握了这些文件的作用,你就能自由地部署、微调、甚至修改AI模型了。 #人工智能 #模型部署 #HuggingFace #技术原理
329 3
|
2月前
|
安全 Ubuntu 物联网
Debian 13.3 Trixie 发布 - 通用操作系统
Debian 13.3 “Trixie” 发布,包含 108 个错误修复和 37 个安全更新
348 0
Debian 13.3 Trixie 发布 - 通用操作系统
|
2月前
|
存储 自然语言处理 Java
为什么 Elasticsearch 搜索这么快?深入理解倒排索引与分词器原理
Elasticsearch 搜索快的秘诀在于倒排索引与分词器。倒排索引通过“词项→文档ID”映射,避免全表扫描;分词器则负责文本的切分与归一化处理,提升检索效率。本文图解剖析其核心原理,助你掌握ES高性能搜索的底层逻辑。(238字)
344 0
|
3月前
|
监控 安全 Unix
iOS 崩溃排查不再靠猜!这份分层捕获指南请收好
从 Mach 内核异常到 NSException,从堆栈遍历到僵尸对象检测,阿里云 RUM iOS SDK 基于 KSCrash 构建了一套完整、异步安全、生产可用的崩溃捕获体系,让每一个线上崩溃都能被精准定位。
870 86
|
2月前
|
人工智能 PyTorch Linux
GLM-4V-9B 视觉多模态模型本地部署教程【保姆级教程】
本教程详细介绍如何在Linux服务器上本地部署智谱AI的GLM-4V-9B视觉多模态模型,涵盖环境配置、模型下载、推理代码及4-bit量化、vLLM加速等优化方案,助力高效实现图文理解与私有化应用。
849 2

热门文章

最新文章