web前端面试高频考点——JavaScript-Web-API 篇(一)DOM、BOM、事件

简介: web前端面试高频考点——JavaScript-Web-API 篇(一)DOM、BOM、事件

JS-Web-API-DOM

DOM 节点操作

获取 DOM 节点

document.getElementById():返回对拥有指定 id 的第一个对象的引用。

document.getElementsByTagName():返回带有指定标签名的对象集合。

document.getElementsByClassName():返回一个包含了所有指定类名的子元素的类数组对象。

document.querySelectorAll():返回与指定的选择器组匹配的文档中的元素列表 (使用深度优先的先序遍历文档的节点)。返回的对象是 NodeList 。

示例:获取 DOM 节点的 Demo

    <div id="div1" class="container">
        <p>一段文字</p>
        <p>一段文字</p>
        <p>一段文字</p>
    </div>
    <div id="div2" class="container">
        <img src="./code.png">
    </div>
  const div1 = document.getElementById('div1')
    console.log('div1', div1)
    const divList = document.getElementsByTagName('div')
    console.log('divList.length', divList.length)
    console.log('divList[1]', divList[1])
    const containerList = document.getElementsByClassName('container')
    console.log('containerList.length', containerList.length)
    console.log('containerList[1]', containerList[1])
    const pList = document.querySelectorAll('p')
    console.log('pList', pList)

5c20c9a7713648c1b4b2f22cefbcee7e.png

DOM 节点的 property 和 attribute

  • property:修改对象属性,不会体现到 html 结构中
  • attribute:修改 html 属性,会改变 html 结构
  • 两者都有可能引起 DOM 的重新渲染

示例 1:property 修改对象属性(推荐使用)

  .container {
        border: 1px solid #ccc;
    }
    .red {
        color: red;
    }
    <div id="div1" class="container">
        <p>一段文字1</p>
        <p>一段文字2</p>
        <p>一段文字3</p>
    </div>
    // property 形式
    const pList = document.querySelectorAll('p')
    const p1 = pList[0]
    p1.style.width = '100px'
    console.log(p1.style.width)
    p1.className = 'red'
    console.log(p1.className)
    console.log(p1.nodeName)
    console.log(p1.nodeType)

fd02493a94e1463cb4bd072f6ace95f0.png

示例 2:attribute 修改 html 属性

  .container {
        border: 1px solid #ccc;
    }
    .red {
        color: red;
    }
    <div id="div1" class="container">
        <p>一段文字1</p>
        <p>一段文字2</p>
        <p>一段文字3</p>
    </div>
    // attribute 
    const pList = document.querySelectorAll('p')
    const p1 = pList[0]
    p1.setAttribute('data-name', 'imooc')
    console.log(p1.getAttribute('data-name'))
    p1.setAttribute('style', 'font-size: 30px;')
    console.log(p1.getAttribute('style'))

345e4cd7ea204c3ea7ec04d6258365b8.png

DOM 结构操作

新增、插入、移动节点

  • 新增节点:createElement
  • 插入节点:appendChild
  • 移动节点:已有的节点插入到别的容器就会发生移动

示例:

    <div id="div1" class="container">
        <p id="p1">一段文字1</p>
        <p>一段文字2</p>
        <p>一段文字3</p>
    </div>
    <div id="div2" class="container"></div>
    const div1 = document.getElementById('div1')
    const div2 = document.getElementById('div2')
    const newP = document.createElement('p')
    // 新建节点
    newP.innerHTML = '新增的一段文字'
    // 插入节点
    div1.appendChild(newP)
    // 移动节点
    const p1 = document.getElementById('p1')
    div2.appendChild(p1)

9d405930b19f4ccf9310cd5cfc7ba074.png

获取子元素列表 & 获取父元素

  • parentNode:父元素
  • childNodes:子元素
  • removeChild:删除子元素

示例 1:div1ChildNodes 不是数组,需要Array.from() 转为数组

    <div id="div1" class="container">
        <p id="p1">一段文字1</p>
        <p>一段文字2</p>
        <p>一段文字3</p>
    </div>
  const div1 = document.getElementById('div1')
  // 获取父元素
    console.log(p1.parentNode)
    // 获取子元素列表
    const div1ChildNodes = div1.childNodes
    console.log(div1.childNodes)
    const divChildNodesP = Array.from(div1ChildNodes).filter(child => {
        if(child.nodeType === 1) {
            return true
        }
        return false
    })
    console.log('divChildNodesP', divChildNodesP)

cd2c25445cf14c13af060c23705e42c2.png

删除子元素

示例:在上文的基础上进行删除子元素

  div1.removeChild(divChildNodesP[0])

b60d866f79eb408b8a8932c31d5e8807.png

如何优化 DOM 操作的性能

DOM 查询做缓存

  • 做缓存,先接收所有的 length,避免循环的时候重复操作 DOM

示例 1:

    // 不缓存 DOM 查询结果
    for(let i = 0; i < document.getElementsByTagName('p').length; i++) {
        // 每次循环,都会计算 length,频繁进行 DOM 查询
    }

示例 2:

    // 缓存 DOM 查询结果
    const pList = document.getElementsByTagName('p')
    const length = pList.length
    for(let i = 0; i < length; i++) {
        // 缓存 length,只进行一次 DOM 查询
    }

将频繁操作改为一次性操作

  • 创建文档片段,把循环的内容先插入到文档片段中

示例 1:频繁的 DOM 操作

    <ul id="list"></ul>
    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)
    }

示例 2:创建文档片段

    <ul id="list"></ul>
    const list = document.getElementById('list')
    // 创建一个文档片段,此时还没有插入到 DOM 树中
    const frag = document.createDocumentFragment()
    // 执行插入
    for(let i = 0; i <= 10; i++) {
        const li = document.createElement('li')
        li.innerHTML = `List item ${i}`
        // 先插入文档片段中
        frag.appendChild(li)
    }
    // 都完成之后,再统一插入到 DOM 树中
    list.appendChild(frag)

4f7faf5719154616a20abbc039012db2.png

JS-Web-API-BOM

BOM 操作相关面试题

navigation 和 screen

  • navigation.userAgent:浏览器用于 HTTP 请求的用户代理头的值
  • screen.width:屏幕宽度
  • screen.height:屏幕高度
  • 01d2d1e26e004e19a6d4f1e50c540558.png

拆解 url 各部分

location.href:返回完整的URL

location.protocol:返回一个URL协议

location.host:返回一个URL的主机名和端口

location.search:返回一个URL的查询部分

location.hash:返回一个URL的锚部分

location.pathname:返回的URL路径名。

23f0fa0814fc4a45a4c16e3ac3c37333.png

JS-Web-API-事件

事件绑定

示例:通用事件绑定函数

  <button id="btn1">一个按钮</button>
  function bindEvent(elem, type, fn) {
        elem.addEventListener(type, fn) 
    }
    const btn1 = document.getElementById('btn1')
    bindEvent(btn1, 'click', event => {
      console.log(event.target) // 
        alert('clicked')
    })

0f282be610e0459ca93c1717983d1a4f.png

事件冒泡

  • 基于 DOM 树形结构
  • 事件会顺着触发元素往上冒泡
  • 应用场景:代理
  • stopPropagation:用于阻止事件冒泡
    <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>
  function bindEvent(elem, type, fn) {
        elem.addEventListener(type, fn)
    }
    const p1 = document.getElementById('p1')
    const body = document.body
    bindEvent(p1, 'click', event => {
        event.stopPropagation() // 阻止冒泡
        console.log('激活')
    })
    bindEvent(body, 'click', event => {
        console.log('取消')
    })

不阻止冒泡,点击激活会冒泡到取消:

5343f1bd88df4fde8fdc063785194822.png

阻止冒泡,点击激活不会冒泡:

c1dfc5fe872a42b6ad73c9dcbda9ccb8.png

事件代理

  • 代码更简洁
  • 减少浏览器内存占用
  • 但是,不要滥用
  • 对于复杂,不好去每个都绑定事件的时候使用

示例:元素 a 把事件处理委托给自己的父元素 div 去处理

    <div id="div1">
        <a href="#">a1</a>
        <a href="#">a2</a>
        <a href="#">a3</a>
        <a href="#">a4</a>
        <button>加载更多...</button>
    </div>
  function bindEvent(elem, type, fn) {
        elem.addEventListener(type, fn)
    }
    const div1 = document.getElementById('div1')
    bindEvent(div1, 'click', event => {
        event.preventDefault() // 阻止页面跳转
        const target = event.target
        if(target.nodeName === 'A') {
            alert(target.innerHTML)
        }
    })

点击 a1-4 会弹出对话框,点击按钮则不会:

b781993a06a44916b284ce8402c8b761.png

通用事件绑定函数(考虑代理)

  • fn 不能是箭头函数,箭头函数无法被 call
    <div id="div1">
        <a href="#">a1</a>
        <a href="#">a2</a>
        <a href="#">a3</a>
        <a href="#">a4</a>
        <button>加载更多...</button>
    </div>
    <button id="btn1">点击</button>
  // 通用事件绑定函数
    function bindEvent(elem, type, selector, fn) {
        // 如果传入三个参数,把 selector 赋值给 fn,selector 置空
        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)
            }
        })
    }
  // 普通绑定
    const btn1 = document.getElementById('btn1')
    bindEvent(btn1, 'click', function(event) {
        event.preventDefault()
        alert(this.innerHTML)
    })
    // 代理绑定
    const div1 = document.getElementById('div1')
    bindEvent(div1, 'click', 'a', function (event) {
        event.preventDefault()
        alert(this.innerHTML)
    })

点击 a1-4 会弹出对话框,点击按钮则不会:

ef160b7729de44c4916443e5a44af923.png

不积跬步无以至千里 不积小流无以成江海

相关文章
|
6天前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
21 2
|
14天前
|
JavaScript 前端开发 索引
js中DOM的基础方法
【10月更文挑战第31天】这些DOM基础方法是操作网页文档结构和实现交互效果的重要工具,通过它们可以动态地改变页面的内容、样式和行为,为用户提供丰富的交互体验。
|
8天前
|
资源调度 前端开发 JavaScript
vite3+vue3 实现前端部署加密混淆 javascript-obfuscator
【11月更文挑战第10天】本文介绍了在 Vite 3 + Vue 3 项目中使用 `javascript-obfuscator` 实现前端代码加密混淆的详细步骤,包括安装依赖、创建混淆脚本、修改 `package.json` 脚本命令、构建项目并执行混淆,以及在 HTML 文件中引用混淆后的文件。通过这些步骤,可以有效提高代码的安全性。
|
15天前
|
JavaScript 前端开发 开发者
.js的dom元素操作
【10月更文挑战第29天】通过灵活运用这些 DOM 元素操作方法,JavaScript 可以实现丰富的网页交互效果,如动态更新页面内容、响应用户操作、创建和删除页面元素等。在实际开发中,开发者可以根据具体的需求和场景,选择合适的 DOM 元素操作方法来实现所需的功能,为用户提供更加流畅和动态的网页体验。
|
16天前
|
设计模式 前端开发 JavaScript
揭秘!前端大牛们如何巧妙利用JavaScript,打造智能交互体验!
【10月更文挑战第30天】前端开发领域充满了无限可能与创意,JavaScript作为核心语言,凭借强大的功能和灵活性,成为打造智能交互体验的重要工具。本文介绍前端大牛如何利用JavaScript实现平滑滚动、复杂动画、实时数据更新和智能表单验证等效果,展示了JavaScript的多样性和强大能力。
32 4
|
14天前
|
机器学习/深度学习 自然语言处理 前端开发
前端神经网络入门:Brain.js - 详细介绍和对比不同的实现 - CNN、RNN、DNN、FFNN -无需准备环境打开浏览器即可测试运行-支持WebGPU加速
本文介绍了如何使用 JavaScript 神经网络库 **Brain.js** 实现不同类型的神经网络,包括前馈神经网络(FFNN)、深度神经网络(DNN)和循环神经网络(RNN)。通过简单的示例和代码,帮助前端开发者快速入门并理解神经网络的基本概念。文章还对比了各类神经网络的特点和适用场景,并简要介绍了卷积神经网络(CNN)的替代方案。
|
14天前
|
移动开发 前端开发 JavaScript
前端实训,刚入门,我用原生技术(H5、C3、JS、JQ)手写【网易游戏】页面特效
于辰在大学期间带领团队参考网易游戏官网的部分游戏页面,开发了一系列前端实训作品。项目包括首页、2021校园招聘页面和明日之后游戏页面,涉及多种特效实现,如动态图片切换和人物聚合效果。作品源码已上传至CSDN,视频效果可在CSDN预览。
22 0
前端实训,刚入门,我用原生技术(H5、C3、JS、JQ)手写【网易游戏】页面特效
|
19天前
|
JavaScript 前端开发 开发者
前端框架对比:Vue.js与Angular的优劣分析与选择建议
【10月更文挑战第27天】在前端开发领域,Vue.js和Angular是两个备受瞩目的框架。本文对比了两者的优劣,Vue.js以轻量级和易上手著称,适合快速开发小型到中型项目;Angular则由Google支持,功能全面,适合大型企业级应用。选择时需考虑项目需求、团队熟悉度和长期维护等因素。
27 1
|
20天前
|
JavaScript 前端开发 API
前端框架对比:Vue.js与Angular的优劣分析与选择建议
【10月更文挑战第26天】前端技术的飞速发展让开发者在构建用户界面时有了更多选择。本文对比了Vue.js和Angular两大框架,介绍了它们的特点和优劣,并给出了在实际项目中如何选择的建议。Vue.js轻量级、易上手,适合小型项目;Angular结构化、功能强大,适合大型项目。
17 1
|
11天前
|
前端开发 JavaScript 安全
vite3+vue3 实现前端部署加密混淆 javascript-obfuscator
【11月更文挑战第7天】本文介绍了在 Vite 3 + Vue 3 项目中使用 `javascript-obfuscator` 实现前端代码加密混淆的详细步骤。包括项目准备、安装 `javascript-obfuscator`、配置 Vite 构建以应用混淆,以及最终构建项目进行混淆。通过这些步骤,可以有效提升前端代码的安全性,防止被他人轻易分析和盗用。