【JS】Chapter15-高阶技巧
站在巨人的肩膀上
黑马程序员前端JavaScript入门到精通全套视频教程,javascript核心进阶ES6语法、API、js高级等基础知识和实战教程
(十五)高阶技巧
1. 深浅拷贝
- 开发中我们经常需要复制一个对象。如果直接用赋值会有下面问题:
// 一个 pink 对象 const pink = {name: 'pink老师',age: 18 } const red = pink console.log(red) // { name: 'pink老师', age: 18 } red.name = 'red老师' console.log(red) // { name: 'red老师', age: 18 } // 但是 pink 对象里面的 name 值也发生了变化 console.log(pink) // { name: 'red老师', age: 18 }
1.1 浅拷贝
- 首先浅拷贝和深拷贝只针对引用类型。
- 浅拷贝:拷贝的是地址
- 常见方法:
- 拷贝对象:Object.assgin() / 展开运算符 {…obj} 拷贝对象
- 拷贝数组:Array.prototype.concat() 或者 […arr]
- 例子1:
const obj = {uname: 'pink' } const o = { ...obj } console.log(o) // { uname: 'pink' } o.uname = 'red' console.log(o) // { uname: 'red' } console.log(obj) // { uname: 'pink' } - 例子2:
// 一个 pink 对象 const pink = {name: 'pink老师',age: 18 } const red = {} Object.assign(red, pink) console.log(red) // { name: 'pink老师', age: 18 } red.name = 'red老师' console.log(red) // { name: 'red老师', age: 18 } // 不会影响 pink 对象 console.log(pink) // { name: 'pink老师', age: 18 } - 例子3:
```js
// 一个 pink 对象
const pink = {
name: ‘pink老师’,
age: 18,
family: {
mother: ‘pink妈妈’
}
}
const red = {}
Object.assign(red, pink)
console.log(red) // { name: ‘pink老师’, age: 18 }
red.name = ‘red老师’
// 更改对象里面的 family 还是会有影响
console.log(red) // { name: ‘red老师’, age: 18 }
// 不会影响 pink 对象
console.log(pink) // { name: ‘pink老师’, age: 18 }- 如果是简单数据类型拷贝值,引用数据类型拷贝的是地址 (简单理解:如果是单层对象,没问题,如果有多层就有问题) - 直接赋值和浅拷贝有什么区别?
- 直接赋值的方法,只要是对象,都会相互影响,因为是直接拷贝对象栈里面的地址
- 浅拷贝如果是一层对象,不相互影响,如果出现多层对象拷贝还会相互影响
- 浅拷贝怎么理解?
- 拷贝对象之后,里面的属性值是简单数据类型直接拷贝值
- 如果属性值是引用数据类型则拷贝的是地址
1.2 深拷贝
- 首先浅拷贝和深拷贝只针对引用类型
- 深拷贝:拷贝的是对象,不是地址
- 常见方法:
- 通过递归实现深拷贝
- lodash/cloneDeep
- 通过JSON.stringify()实现
1.2.1 通过递归实现深拷贝
- 函数递归:
- 如果一个函数在内部可以调用其本身,那么这个函数就是递归函数
- 简单理解:函数内部自己调用自己, 这个函数就是递归函数
- 递归函数的作用和循环效果类似
- 由于递归很容易发生“栈溢出”错误(stack overflow),所以必须要加退出条件return
- 例子:
let num = 1 // fn 就是递归函数 function fn() {console.log('我要打印6次')if(num >= 6) {return}num++fn() // 函数内部调用函数自己 } fn() - 利用递归函数实现 setTimeout 模拟 setInterval效果。
function getTime() {const time = new Date().toLocalString()console.log(time)setTimeout(getTime, 1000) // 定时器调用当前函数 } getTime() - 通过递归函数实现深拷贝(简版)
const o = {} function deepCopy(newObj, oldObj) {for(let k in oldObj) {if(oldObj[k] instanceof Array) {newObj[k] = []deepCopy(newObj[k], oldObj[k])}else if(oldObj[k] instanceof Object) {newObj[k] = {}deepCopy(newObj[k], oldObj[k])}else {newObj[k] = oldObj[k]}} }
1.2.2 js库lodash里面cloneDeep内部实现了深拷贝
const obj = {uname: 'pink',age: 18,hobby: ['篮球', '足球'],family: {baby: '小pink'}
}
// 语法:_.cloneDeep(要被克隆的对象)
const o = _.cloneDeep(obj)
console.log(o)
o.family.baby = '老pink'
console.log(obj)
1.2.3 通过JSON.stringify()实现
const obj = {uname: 'pink',age: 18,hobby: ['篮球', '足球'],family: {baby: '小pink'}
}
const o = JSON.parse(JSON.stringify(obj))
console.log(o)
o.family.baby = '老pink'
console.log(obj)
2. 异常处理
2.1 throw 抛异常
- 异常处理是指预估代码执行过程中可能发生的错误,然后最大程度的避免错误的发生导致整个程序无法继续运行
- 总结:
- throw 抛出异常信息,程序也会终止执行
- throw 后面跟的是错误提示信息
- Error 对象配合 throw 使用,能够设置更详细的错误信息
- 例子:
function counter(x, y) {if(!x || !y) {// throw '参数不能为空!';throw new Error('参数不能为空!')}return x + y } counter()
2.2 try/catch 捕获异常
- 我们可以通过try / catch 捕获错误信息(浏览器提供的错误信息) try 试试 catch 拦住 finally 最后
- 总结:
- try…catch 用于捕获错误信息
- 将预估可能发生错误的代码写在 try 代码段中
- 如果 try 代码段中出现错误后,会执行 catch 代码段,并截获到错误信息
- finally 不管是否有错误,都会执行
- 例子:
function foo() {try {// 查找 DOM 节点const p = document.querySelectro('.p')p.style.color = 'red'} catch(error) {// try 代码段中执行有错误时,会执行 catch 代码段// 查看错误信息console.log(error.message)// 终止代码继续执行return}finally {alert('执行')}console.log('如果出现错误,我的语句不会执行') } foo()
2.3 debugger
- 我们可以通过 try / catch 捕获错误信息(浏览器提供的错误信息)
- 例子:
const arr = [1, 3, 5] const newArr = arr.map((item, index) => {debuggerconsole.log(item) // 当前元素console.log(index) // 当前元素索引号return item + 10 // 让当前元素 + 10 }) console.log(newArr) // [11, 13, 15]
3. 处理this
- this 是 JavaScript 最具“魅惑”的知识点,不同的应用场合 this 的取值可能会有意想不到的结果,在此我们对以往学习过的关于【 this 默认的取值】情况进行归纳和总结。
3.1 this指向
3.1.1 普通函数this指向
- 普通函数的调用方式决定了 this 的值,即【谁调用 this 的值指向谁】
- 普通函数没有明确调用者时 this 值为 window,严格模式下没有调用者时 this 的值为 undefined。
- 例子1:
// 普通函数 function sayHi() {console.log(this) } // 函数表达式 const sayHello = function() {console.log(this) } // 函数的调用方式决定了 this 的值 sayHi() // window windows.sayHi() - 例子2:
// 普通对象 const user = {name: '小明',walk: function() {console.log(this)} } // 动态为 user 添加方法 user.sayHi = sayHi user.sayHello = sayHello // 函数的调用方式决定了 this 的值 user.sayHi() user.sayHello() - 例子3:
<script>'use strict'function fn() {console.log(this) // undefined}fn() </script>
3.1.2 箭头函数this指向
- 箭头函数中的 this 与普通函数完全不同,也不受调用方式的影响,事实上箭头函数中并不存在 this !
- 箭头函数会默认帮我们绑定外层 this 的值,所以在箭头函数中 this 的值和外层的 this 是一样的
- 箭头函数中的this引用的就是最近作用域中的this
- 向外层作用域中,一层一层查找this,直到有this的定义
- 例子1:
console.log(this) // 此处为 window // 箭头函数 const sayHi = function() {console.log(this) // 该箭头函数中的 this 为函数声明环境中 this 一致 } - 例子2:
// 普通对象 const user = {name: '小明',// 该箭头函数中的 this 为函数声明环境中 this 一致walk: () => {console.log(this)} } - 注意情况1:
- 在开发中【使用箭头函数前需要考虑函数中 this 的值】,事件回调函数使用箭头函数时,this 为全局的 window
- 因此DOM事件回调函数如果里面需要DOM对象的this,则不推荐使用箭头函数
- 例子:
// DOM 节点 const btn = document.querySelector('.btn') // 箭头函数,此时 this 指向了 window btn.addEventListener('click', () => {console.log(this) }) // 普通函数,此时 this 指向了 DOM 对象 btn.addEventListener('click', function () {console.log(this) })
- 注意情况2:
- 同样由于箭头函数 this 的原因,基于原型的面向对象也不推荐采用箭头函数
- 例子:
function Person() { } // 原型对象上添加了箭头函数 Person.prototype.walk = () => {console.log('人都要走路...')console.log(this); // window } const p1 = new Person() p1.walk()
- 总结:
- 函数内不存在this,沿用上一级的
- 不适用
- 构造函数,原型函数,dom事件函数等等
- 适用
- 需要使用上层this的地方
- 使用正确的话,它会在很多地方带来方便,后面我们会大量使用慢慢体会
3.2 改变this
- JavaScript 中还允许指定函数中 this 的指向,有 3 个方法可以动态指定普通函数中 this 的指向:
- call()
- apply()
- bind()
3.2.1 call()–了解
- 使用 call 方法调用函数,同时指定被调用函数中 this 的值
- 语法:
fun.call(thisArg, arg1, arg2, ...)- thisArg:在 fun 函数运行时指定的 this 值
- arg1,arg2:传递的其他参数
- 返回值就是函数的返回值,因为它就是调用函数
- 例子1:
const obj = {name: 'pink' } function fn() {console.log(this) // 指向 obj {name: 'pink'} } fn.call(obj) - 例子2:
const obj = {name: 'pink' } function fn(x, y) {console.log(this) // 指向 obj {name: 'pink'}console.log(x + y) // 传递过来的参数相加 } fn.call(obj, 1, 2)
3.2.2 apply()-理解
- 使用 apply 方法调用函数,同时指定被调用函数中 this 的值
- 语法:
fun.apply(thisArg, [argsArray])- thisArg:在fun函数运行时指定的 this 值
- argsArray:传递的值,必须包含在数组里面
- 返回值就是函数的返回值,因为它就是调用函数
- 因此 apply 主要跟数组有关系,比如使用 Math.max() 求数组的最大值
- 例子:
// 求和函数 function counter(x, y) {return x + y } // 调用 counter 函数,并传入参数 let result = counter.apply(null, [5, 10]) console.log(result) - 求数组最大值2个方法:
// 求数组最大值 const arr = [3, 5, 2, 9] console.log(Math.max.apply(null, arr)) // 9,利用apply console.log(Math.max(...arr)) // 9,利用展开运算符
3.2.3 bind()-重点
- bind() 方法不会调用函数。但是能改变函数内部this 指向
- 语法:
fun.bind(thisArg, arg1, arg2, ...)- thisArg:在 fun 函数运行时指定的 this 值
- arg1,arg2:传递的其他参数
- 返回由指定的 this 值和初始化参数改造的 原函数拷贝 (新函数)
- 因此当我们只是想改变 this 指向,并且不想调用这个函数的时候,可以使用 bind,比如改变定时器内部的this指向.
- 例子:
// 普通函数 function sayHi() {console.log(this) } let user = {name: '小明',age: 18 } // 调用 bind 指定 this 的值 let sayHello = sayHi.bind(user); // 调用使用 bind 创建的新函数 sayHello()
3.2.4 call apply bind 总结
- 相同点:
- 都可以改变函数内部的this指向.
- 区别点:
- call 和 apply 会调用函数, 并且改变函数内部this指向.
- call 和 apply 传递的参数不一样, call 传递参数 aru1, aru2…形式,apply 必须数组形式[arg]
- bind 不会调用函数, 可以改变函数内部this指向.
- 主要应用场景:
- call 调用函数并且可以传递参数
- apply 经常跟数组有关系. 比如借助于数学对象实现数组最大值最小值
- bind 不调用函数,但是还想改变this指向. 比如改变定时器内部的this指向.
4. 性能优化
4.1 防抖
- 所谓防抖(debounce),就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间
- 现实例子:北京买房政策,需要连续5年的社保,如果中间有一年断了社保,则需要从新开始计算
- 开发使用场景:搜索框防抖
- 假设输入就可以发送请求,但是不能每次输入都去发送请求,输入比较快发送请求会比较多
- 我们设定一个时间,假如300ms, 当输入第一个字符时候,300ms后发送请求,但是在200ms的时候又输入了一个字符,则需要再等300ms 后发送请求
- 利用防抖来处理-鼠标滑过盒子显示文字
const box = document.querySelector('.box') let i = 1 function mouseMove() {box.innerHTML = i++ } function debounce(fn, t = 500) {let timeIdreturn function () {// 如果有定时器,先清除if(timeId)clearTimeout(timeId)// 开启定时器timeId = setTimeout(function() {fn()}, t)} } box.addEventListener('mousemove', debounce(mouseMove, 500))- 核心思路:利用定时器实现,当鼠标滑过,判断有没有定时器,还有就清除,以最后一次滑动为准开启定时器
4.2 节流
-
所谓节流(throttle),就是指连续触发事件但是在 n 秒中只执行一次函数
-
现实例子:只有等到了上一个人做完核酸,整个动作完成了,第二个人才能排队跟上
-
开发使用场景:小米轮播图点击效果、鼠标移动、页面尺寸缩放resize、滚动条滚动 就可以加节流
- 假如一张轮播图完成切换需要300ms,不加节流效果,快速点击,则嗖嗖嗖的切换
- 加上节流效果,不管快速点击多少次,300ms时间内,只能切换一张图片。
-
利用节流来处理-鼠标滑过盒子显示文字:
const box = document.querySelector('.box') let i = 1 function mouseMove() {box.innerHTML = i++// 如果存在开销较大操作,大量数据处理,大量dom操作,可能会卡 } function throttle(fn, t = 500) {let startTime = 0return function () {let now = Date.now()if(now - startTime >= t) {fn()startTime = now}} } box.addEventListener('mousemove', throttle(mouseMove, 500))- 利用节流的方式,鼠标经过,500ms,数字才显示
-
节流和防抖的区别是?
- 节流: 就是指连续触发事件但是在 n 秒中只执行一次函数,比如可以利用节流实现 1s 之内只能触发一次鼠标移动事件
- 防抖:如果在 n 秒内又触发了事件,则会重新计算函数执行时间
-
节流和防抖的使用场景是?
- 节流: 鼠标移动,页面尺寸发生变化,滚动条滚动等开销比较大的情况下
- 防抖: 搜索框输入,设定每次输入完毕n秒后发送请求,如果期间还有输入,则从新计算时间
4.3 Lodash 库实现节流和防抖
-
节流
const box = document.querySelector('.box') let i = 1 function mouseMove() {box.innerHTML = i++// 如果存在开销较大操作,大量数据处理,大量dom操作,可能会卡 } box.addEventListener('mousemove', _.throttle(mouseMove, 1000)) -
防抖
const box = document.querySelector('.box') let i = 1 function mouseMove() {box.innerHTML = i++// 如果存在开销较大操作,大量数据处理,大量dom操作,可能会卡 } box.addEventListener('mousemove', _.debounce(mouseMove, 1000))
5. 节流综合案例
页面打开,可以记录上一次的视频播放位置
- 思路:
- 在ontimeupdate事件触发的时候,每隔1秒钟,就记录当前时间到本地存储
- 下次打开页面, onloadeddata 事件触发,就可以从本地存储取出时间,让视频从取出的时间播放,如果没有就默认为0s
- 获得当前时间 video.currentTime
- 代码:
const video = document.querySelector('video') video.ontimeupdate = _.throttle(() => {localStorage.setItem('currentTime', video.currentTime) }, 1000) video.onloadeeddata = () => {video.currentTime = local.getItem('currentTime') || 0 }
相关文章:
【JS】Chapter15-高阶技巧
站在巨人的肩膀上 黑马程序员前端JavaScript入门到精通全套视频教程,javascript核心进阶ES6语法、API、js高级等基础知识和实战教程 (十五)高阶技巧 1. 深浅拷贝 开发中我们经常需要复制一个对象。如果直接用赋值会有下面问题:/…...
Google Chrome 任意文件读取 (CVE-2023-4357)漏洞
漏洞描述 该漏洞的存在是由于 Google Chrome 中用户提供的 XML 输入验证不足。远程攻击者可以创建特制网页,诱骗受害者访问该网页并获取用户系统上的敏感信息。远程攻击者可利用该漏洞通过构建的 HTML 页面绕过文件访问限制,导致chrome任意文件读取。Li…...
psql 模式(SCHEMA)
模式是数据库领域的一个基本概念,有些数据库把模式和用户合二为一了,而postgresql则是有清晰的模式定义。 模式是数据库中的一个概念,可以理解为一个命名空间或目录,不同模式下可以有相同名称的表、函数等对象而不会产生冲突。提出…...
网络吞吐量 公网带宽有关吗?
环境: 华为交换机 深信服防火墙 问题描述: 网络吞吐量 公网带宽有关吗? 解决方案: 网络吞吐量网络吞吐量是指在特定时间内通过网络传输的数据量。它衡量了网络设备(如防火墙、交换机、路由器)或网络连…...
Linux设置静态IP
Linux设置静态IP 使用ip addr查看ip,如下所示就是动态IP 1、什么是静态IP? 静态ip就是固定的ip,需要手动设置。静态IP地址(又称固定IP地址)是长期分配给一台计算机或网络设备使用的 IP 地址。一般来说,一…...
六、Big Data Tools安装
1、安装 在Jetbrains的任意一款产品中,均可安装Big Data Tools这个插件。 2、示例 下面以DadaGrip为例: (1)打开插件中心 (2)搜索Big Data Tools,下载 3、链接hdfs (1࿰…...
数据结构【DS】特殊二叉树
完全二叉树 叶子结点只能出现在最下层和次下层, 最下层的叶子结点集中在树的左部完全二叉树中, 度为1的节点数 0个或者1个【计算时可以用这个快速计算, 配合𝑛0𝑛21】若n为奇数,则分支节点每个都有左右孩子;若n为偶数࿰…...
【Spring Boot】如何在Linux系统中快速启动Spring Boot的jar包
在Linux系统中先安装java的JDK 然后编写下列service.sh脚本,并根据自己的需求只需要修改export的log_path、exec_cmd参数即可 # 配置运行日志输出的路径 export log_path/usr/local/project/study-pro/logs # 当前服务运行的脚本命令 export exec_cmd"nohup /u…...
交替最小二乘法
前置概念导入 协同过滤(Collaborative Filtering):这是一种推荐系统的方法,依据用户之间或物品之间的相似性来进行推荐。协同过滤通常分为两种主要类型:用户基于(user-based)和物品基于…...
封面从这里取好啦
文章目录 前端NPMViteNode.js 后端JavaMavenPython 数据库算法 前端 NPM Vite Node.js 后端 Java Maven Python 数据库 算法...
DM8共享集群DSC初始化DB实例报错
DM8共享集群DSC初始化DB实例报错 问题描述 启动dmcss和dmasmsvr服务启动后,初始化DB实例提示如下报错: [dmdbalocalhost DSC0]$ /dmdb8/dmdbms/bin/dminit control/dmdb8/dmdbms/dsc_config/DSC0/dminit.ini initdb V8 db version: 0x7000c file dm.k…...
大师学SwiftUI第18章Part1 - 图片选择器和相机
如今,个人设备主要用于处理图片、视频和声音,苹果的设备也不例外。SwiftUI可以通过Image视图显示图片,但需要其它框架的支持来处理图片、在屏幕上展示视频或是播放声音。本章中我们将展示Apple所提供的这类工具。 图片选择器 Swift…...
【电子通识】USB3.0和USB2.0有什么区别?
版本 USB2.0是2000年4月27日由USB-IF组织提出了USB2.0总线协议规范。 USB3.0是2008年11月17日由USB-IF组织提出了超高速USB3.0规范。 图标对比 USB2.0的标志就是和USB1.1的标志基本上没啥区别,还是以前的那个样子,使用黑色颜色用标识 USB3.0它有一个S…...
在VSCode创建vue项目,出现“因为在此系统上禁止运行脚本”问题
问题:vue : 无法加载文件 C:\Users\***\***\Roaming\npm\vue.ps1,因为在此系统上禁止运行脚本。有关详细信息,请参阅 ht tps:/go.microsoft.com/fwlink/?LinkID135170 中的 about_Execution_Policies。 所在位置 行:1 字符: 1 解决ÿ…...
OpenCV快速入门:目标检测——轮廓检测、轮廓的距、点集拟合和二维码检测
文章目录 前言一、轮廓检测1.1 图像轮廓的概念1.2 轮廓检测算法简介1.3 轮廓检测基本步骤1.4 轮廓检测函数说明1.4.1 轮廓发现1.4.2 轮廓面积1.4.3 轮廓周长1.4.4 轮廓外接多边形1.4.5 点到轮廓距离1.4.6 凸包检测 1.5 轮廓检测代码实现 二、轮廓的距2.1 几何距2.2 中心距2.3 H…...
基于STM32的烟雾浓度检测报警仿真设计(仿真+程序+讲解视频)
这里写目录标题 📑1.主要功能📑2.仿真📑3. 程序📑4. 资料清单&下载链接📑[资料下载链接](https://docs.qq.com/doc/DS0VHTmxmUHBtVGVP) 基于STM32的烟雾浓度检测报警仿真设计(仿真程序讲解) 仿真图prot…...
Jenkins 下载安装
下载 Jenkins 选择Download LTS是稳定版本,尽量选择稳定版本,然后选择你的开发系统. 安装 Jenkins需要JAVA环境,所以安装JAVA环境 Java Jenkins支持17、21等几个版本的Java,OpenJDK JDK 21.0.1 GA Release 安装不要安装到C盘,这个后面会占较大的…...
MySQL 事务的底层原理和 MVCC(二)
7.2. undo 日志 7.2.1. 事务回滚的需求 我们说过事务需要保证原子性,也就是事务中的操作要么全部完成,要么什么也不做。但是偏偏有时候事务执行到一半会出现一些情况,比如: 情况一:事务执行过程中可能遇到各种错误&a…...
(C++)验证回文字符串
愿所有美好如期而遇 力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/valid-pali…...
代码随想录算法训练营第25天|216.组合总和III 17.电话号码的字母组合
JAVA代码编写 216. 组合总和III 找出所有相加之和为 n 的 k 个数的组合,且满足下列条件: 只使用数字1到9每个数字 最多使用一次 返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。 示例 1: 输入: k …...
龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...
【Python】 -- 趣味代码 - 小恐龙游戏
文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...
Leetcode 3577. Count the Number of Computer Unlocking Permutations
Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接:3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯,要想要能够将所有的电脑解锁&#x…...
微信小程序云开发平台MySQL的连接方式
注:微信小程序云开发平台指的是腾讯云开发 先给结论:微信小程序云开发平台的MySQL,无法通过获取数据库连接信息的方式进行连接,连接只能通过云开发的SDK连接,具体要参考官方文档: 为什么? 因为…...
Android15默认授权浮窗权限
我们经常有那种需求,客户需要定制的apk集成在ROM中,并且默认授予其【显示在其他应用的上层】权限,也就是我们常说的浮窗权限,那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...
智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制
在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...
ubuntu22.04有线网络无法连接,图标也没了
今天突然无法有线网络无法连接任何设备,并且图标都没了 错误案例 往上一顿搜索,试了很多博客都不行,比如 Ubuntu22.04右上角网络图标消失 最后解决的办法 下载网卡驱动,重新安装 操作步骤 查看自己网卡的型号 lspci | gre…...
Appium下载安装配置保姆教程(图文详解)
目录 一、Appium软件介绍 1.特点 2.工作原理 3.应用场景 二、环境准备 安装 Node.js 安装 Appium 安装 JDK 安装 Android SDK 安装Python及依赖包 三、安装教程 1.Node.js安装 1.1.下载Node 1.2.安装程序 1.3.配置npm仓储和缓存 1.4. 配置环境 1.5.测试Node.j…...
【Java】Ajax 技术详解
文章目录 1. Filter 过滤器1.1 Filter 概述1.2 Filter 快速入门开发步骤:1.3 Filter 执行流程1.4 Filter 拦截路径配置1.5 过滤器链2. Listener 监听器2.1 Listener 概述2.2 ServletContextListener3. Ajax 技术3.1 Ajax 概述3.2 Ajax 快速入门服务端实现:客户端实现:4. Axi…...
