项目优化的方法

news2024/11/19 17:45:28

持续更新中…

目录

  • 性能
    • 防抖、节流
      • 防抖(debounce)
      • 节流(throttle)
        • 防抖节流的区别:
    • 图片/视频/音频压缩
    • 减少请求发送次数
    • 减少重绘与回流
    • 经常要切换消失与出现状态的节点用v-show而不用v-if
    • 按需引入
    • 路由懒加载
    • 懒加载
      • 图片懒加载
      • 列表懒加载
    • 精灵/雪碧图
    • Webpack优化前端性能
    • 提高Webpack的构建速度
  • 安全性
    • XSS攻击
    • CSRF攻击

性能

防抖、节流

防抖(debounce)

防抖严格算起来应该属于性能优化的知识,但实际上遇到的频率相当高,处理不当或者放任不管就容易引起浏览器卡死。

从滚动条监听的例子说起

function showTop  () {
    var scrollTop = document.documentElement.scrollTop;
    console.log('滚动条位置:' + scrollTop);
}
window.onscroll  = showTop

在运行的时候会发现存在一个问题:这个函数的默认执行频率,太!高!了!。 高到什么程度呢?以chrome为例,我们可以点击选中一个页面的滚动条,然后点击一次键盘的【向下方向键】,会发现函数执行了8-9次!

然而实际上我们并不需要如此高频的反馈,毕竟浏览器的性能是有限的,不应该浪费在这里,所以接着讨论如何优化这种场景。

基于上述场景,首先提出第一种思路:在第一次触发事件时,不立即执行函数,而是给出一个期限值比如200ms,然后

  1. 如果在200ms内没有再次触发滚动事件,那么就执行函数
  2. 如果在200ms内再次触发滚动事件,那么当前的计时取消,重新开始计时

效果:如果同样的事件它们触发的时间间隔小于规定的间隔,那么只执行一次该事件的回调函数

实现:既然前面都提到了计时,那实现的关键就在于setTimeout这个函数,由于还需要一个变量来保存计时,考虑维护全局纯净,可以借助闭包来实现

function debounce(fn,delay){
    let timer = null //借助闭包
    return function() {
        if(timer){
            clearTimeout(timer) //清除之前的定时器
            // timer=null // 测试过了,这一句没有也行
        }
        timer = setTimeout(fn,delay) //开启新的定时器
    }
}
// 然后是旧代码
function showTop  () {
    var scrollTop = document.documentElement.scrollTop;
    console.log('滚动条位置:' + scrollTop);
}
window.onscroll = debounce(showTop,300)//滚动的时候会触发多次debounce()

防抖通用模板

function debounce(fn,delay){
    let timer = null //借助闭包
    return function() {
    	let context=this, args=[...arguments] // 保存this对象及参数
        if(timer){
            clearTimeout(timer) //清除之前的定时器
            // timer=null // 测试过了,这一句没有也行
        }
        timer = setTimeout(()=>{
        	fn.apply(context,args)
        },delay) //开启新的定时器
    }
}
// 原来事件的回调
function fn(<事件回调的一些参数>) {
	// 回调函数的操作
}
事件绑定的对象.事件类型 = debounce(fn,<时间>,<事件回调的一些参数>)//滚动的时候会触发多次

到这里,已经把防抖实现了

防抖定义

对于短时间内连续触发的事件(上面的滚动事件),防抖的含义就是让某个时间期限(如上面的1000毫秒)内,事件处理函数只执行一次

实时效果反馈

1. 以下是关于定时器防抖代码,横线处填写代码是:

function debounce(fn,delay){
    let timer = null 
    return function() {
        if(timer){
            _2_(timer) 
        }
        timer = _1_(fn,delay) 
    }
}
function showTop  () {
    var scrollTop = document.documentElement.scrollTop;
    console.log('滚动条位置:' + scrollTop);
}
window.onscroll = debounce(showTop,300)

A setTimeout clearInterval

B setTimeout clearTimeout

C setInterval clearTimeout

D setInterval clearInterval

答案

1=>B

节流(throttle)

节流严格算起来应该属于性能优化的知识,但实际上遇到的频率相当高,处理不当或者放任不管就容易引起浏览器卡死

继续思考,使用上面的防抖方案来处理问题的结果是

如果在限定时间段内,不断触发滚动事件(比如某个用户闲着无聊,按住滚动不断的拖来拖去),只要不停止触发,理论上就永远不会输出当前距离顶部的距离

但是如果产品同学的期望处理方案是:即使用户不断拖动滚动条,也能在某个时间间隔之后给出反馈呢?

其实很简单:我们可以设计一种类似控制阀门一样定期开放的函数,也就是让函数执行一次后,在某个时间段内暂时失效,过了这段时间后再重新激活(类似于技能冷却时间)

效果:如果短时间内大量触发同一事件,那么在回调执行一次之后,该回调在指定的时间期限内不会再触发,过了这段时间才可以

实现
个人推荐时间戳版,因为定时器版第一次触发的回调会在delay时间后执行
时间戳版

function throttle(fn, delay) {
    var preTime=Date.now() // 获取当前时间戳,这个变量必须在外层函数和内层函数之间定义。否则每次调用throttle函数preTime的值都是调用throttle函数时的时间,无法达到计算时间段的效果
    return function(){
        var context =this, args=[...arguments], nowTime=Date.now()
        if(nowTime-preTime>delay){
            fn.apply(context,args)
            preTime=Date.now()
        }
    }
}

定时器版
这里借助setTimeout来做一个简单的实现,加上一个状态位valid来表示当前函数是否处于工作状态

function throttle(fn,delay){
    let timer = null // 初始肯定是不被冻结的
    return function() {
    let context=this, args=[...arguments];
       if(!timer){
           timer=setTimeout(function(){
           			fn().apply(context,args)
            		timer = null // 记得执行完定时器中的操作后将timer置空,timer为null的时候表示在设定的时间外,没有被冻结
        		 }, delay)
       }
    }
}

function showTop  () {
    var scrollTop = document.documentElement.scrollTop;
    console.log('滚动条位置:' + scrollTop);
}
window.onscroll = throttle(showTop,300) 

如果一直拖着滚动条进行滚动,那么会以300ms的时间间隔,持续输出当前位置和顶部的距离

讲完了这两个技巧,下面介绍一下平时开发中常遇到的场景:

  1. 搜索框input事件,例如要支持输入实时搜索可以使用节流方案(间隔一段时间就必须查询相关内容),或者实现输入间隔大于某个值(如500ms),就当做用户输入完成,然后开始搜索,具体使用哪种方案要看业务需求
  2. 页面resize事件,常见于需要做页面适配的时候。需要根据最终呈现的页面情况进行dom渲染(这种情形一般是使用防抖,因为只需要判断最后一次的变化情况)

实时效果反馈

1. 以下是关于定时器节流代码,横线处填写代码是:

function throttle(fn,delay){
    let valid = true
    return function() {
       if(_1_){
           return false 
       }
        valid = false
        _2_(function(){
            fn()
            valid = true;
        }, delay)
    }
}

A valid setTimeout

B valid setInterval

C !valid setTimeout

D !valid setInterval

答案

1=>C

防抖节流的区别:

防抖:从字面上看是为了避免短时间内大量同样事件回调执行的次数,在规定时间间隔内触发的事件,会导致计时重新开始,以最后一次事件为准
节流:从字面上看是为了减少事件回调执行的次数,事件触发后一段时间内不可再次执行事件回调,有一段事件冻结的时间,但不会重新开始计时

图片/视频/音频压缩

减少请求发送次数

减少重绘与回流

经常要切换消失与出现状态的节点用v-show而不用v-if

按需引入

比如按需引入element-ui中的组件

路由懒加载

懒加载

使用场景:懒加载适用于图片或列表较多,页面列表较长(长列表)的场景中。由于很多图片和列表还没出现在视口中,所以没有必要去加载它们浪费性能。当用户滚动页面快要看到它们才发起请求,加载图片或列表
实现原理:当图片或列表出现或接近可视区时才加载图片。对于图片,将图片的真实地址赋值给图片src属性即可。

图片懒加载

方法一(推荐,简单,但兼容性不太好):设置<img src="图片地址" loading="lazy" /><img src="图片地址" loading="lazy" decoding="async" />
详细参考https://segmentfault.com/a/1190000020109563

decoding:为浏览器提供图像解码方式上的提示。允许的值:

  • sync:同步解码图像,实现与其他内容互斥的原子渲染。
  • async:异步解码图像,以减少其他内容的渲染延迟。
  • auto:默认值:不指定解码方式,由浏览器决定哪一种对用户来说是最合适的。

loading:指示浏览器应当如何加载该图像。允许的值:

  • eager:立即加载图像,不管它是否在可视视口(visible viewport)之外(默认值)。
  • lazy:延迟加载图像,直到它和视口接近到一个计算得到的距离(由浏览器定义)。目的是在需要图像之前,避免加载图像所需要的网络和存储带宽。这通常会提高大多数典型用场景中内容的性能。

这是新增的属性,注意需要考虑兼容性
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
方法二(兼容性较好,但性能差):监听scroll事件,比较图片距离视口顶部和窗口大小的关系
window.innerHeight:浏览器可视区的高度
document.body.scrollTop或document.documentElement.scrollTop:页面滚动的过的距离,document.documentElement是一个会返回文档对象(document)的根元素的只读属性(如 HTML 文档的 元素)。
imgs.offsetTop:是元素顶部距离文档顶部的高度(包括滚动条的距
离)
图 片 加 载 条 件 : img.offsetTop < window.innerHeight +document.body.scrollTop;
在这里插入图片描述
img.getBoundingClientRect().top<window.innerHeight
在这里插入图片描述
Element.getBoundingClientRect() 方法返回一个 DOMRect 对象,其提供了元素的大小及其相对于视口的位置。
在这里插入图片描述

代码实现
在这里插入图片描述
缺点:触发太多次了,每次触发滚动事件都会导致遍历所有图片,而且即使图片已经加载了还可以触发滚动事件,比较消耗性能,可以对滚动事件做节流处理
方法三:IntersectionObserver(性能好,但兼容性不太好)
参考:https://www.bilibili.com/video/BV1FU4y157Li
创建IntersectionObserver实例时,IntersectionObserver构造函数接受一个回调函数,这个回调函数在观察的目标元素与视口交叉或没有交叉时(出现在视口或从视口消失)都会触发。该回调函数有一个参数entries,entries是IntersectionObserver实例监听(observe)的对象组成的数组
IntersectionObserver.observe():使 IntersectionObserver 开始监听一个目标元素。
IntersectionObserver.unobserve():使 IntersectionObserver 停止监听特定目标元素。
在这里插入图片描述
entries的每个元素有isIntersecting属性,表示监听的元素是否与视口交叉(即是否出现在视口中),target属性表示监听的Element元素

<body>
    <p>3. 验证Referer(不能完全保证避免CSRF攻击)
        HTTP请求头有个Referer字段,用于记录请求的来源。可以添加个请求拦截器,若不是来自规定页面的请求,服务器则会拒绝(用户正常发起请求的源地址与黑客冒充用户身份发起请求的源地址是不一样的)。
        但这种方法不能完全保证避免CSRF攻击,因为有些浏览器的HTTP请求头中的字段是可以篡改的,黑客可能通过篡改Referer字段伪造成合法的请求源地址,从而避开请求拦截器的拦截。
    </p>
    <div style="height: 2000px;"></div>
    <img data-src="https://img-blog.csdnimg.cn/a5b8a100c3624a87933fdae1527f0b24.png" >
    <img data-src="https://img-blog.csdnimg.cn/f8f529805ae540dd8289a44bcb490afd.png" >
    <img data-src="https://i0.hdslb.com/bfs/banner/d57e8c0786fd289fc0771efa92de3d227f85a227.png@976w_550h_1c_!web-home-carousel-cover.webp"
        >
    <script>
        const imgs = document.querySelectorAll('img')
        
        const observer = new IntersectionObserver((entries) => {
            console.log(entries)
            entries.forEach((entry) => {
                const img = entry.target
                console.log(img);
            })
        })
        imgs.forEach((img)=>{
            observer.observe(img)
        })
    </script>
</body>

初始控制台输出
在这里插入图片描述
懒加载代码实现:

<body>
    <p>3. 验证Referer(不能完全保证避免CSRF攻击)
        HTTP请求头有个Referer字段,用于记录请求的来源。可以添加个请求拦截器,若不是来自规定页面的请求,服务器则会拒绝(用户正常发起请求的源地址与黑客冒充用户身份发起请求的源地址是不一样的)。
        但这种方法不能完全保证避免CSRF攻击,因为有些浏览器的HTTP请求头中的字段是可以篡改的,黑客可能通过篡改Referer字段伪造成合法的请求源地址,从而避开请求拦截器的拦截。
    </p>
    <div style="height: 1000px;"></div>
    <img data-src="https://img-blog.csdnimg.cn/a5b8a100c3624a87933fdae1527f0b24.png">
    <img data-src="https://img-blog.csdnimg.cn/f8f529805ae540dd8289a44bcb490afd.png">
    <img
        data-src="https://i0.hdslb.com/bfs/banner/d57e8c0786fd289fc0771efa92de3d227f85a227.png@976w_550h_1c_!web-home-carousel-cover.webp">
    <script>
        const imgs = document.querySelectorAll('img')
        // 创建IntersectionObserver实例,并定义目标元素与视口交叉或失去交叉时触发的回调函数
        const callback = (entries) => {
            // console.log(entries)
            entries.forEach((entry) => {
                if (entry.isIntersecting) { // 图片出现在视口(与视口交叉)中才加载图片
                    const img = entry.target
                    const data_src = img.getAttribute('data-src')
                    img.setAttribute('src', data_src) // 给图片的src属性赋值,使图片加载
                    observer.unobserve(img) // 加载图片后,记得取消对已加载图片的监听,否则图片加载后与视口交叉或失去交叉时仍会触发回调函数
                    console.log('触发');
                }
            })
        }
        const observer = new IntersectionObserver(callback)
        // 给IntersectionObserver实例设置监听的目标
        imgs.forEach((img) => {
            observer.observe(img)
        })
    </script>
</body>

疑惑:我这边实际执行改段代码,第一个图片出现时就加载了全部图片

列表懒加载

精灵/雪碧图

Webpack优化前端性能

提高Webpack的构建速度

安全性

XSS攻击

CSRF攻击

参见

  1. CSRF 攻击和防御 ——bilibili
  2. 为什么Cookie 无法防止CSRF攻击,而token可以?——bilibili
  3. 史上最详细的CSRF攻击与防御,看完必有收获!——掘金
  4. MDN官方参考

CSRF(Cross Site Request Forgery)。黑客冒充合法用户的身份做非用户本意的请求。

防御CSRF的方法

  1. 尽量用POST请求代替GET请求。但这种方法不能完全避免CSRF攻击
    如下所示,攻击者可以通过这样的代码(iframe+form+script标签)进行攻击。
    在这里插入图片描述
  2. 加入验证流程
    比如验证码,滑动滑块等验证行为,以确保该操作是用户发起的,而不是黑客发起的。
    在这里插入图片描述
  3. 验证Referer(不能完全保证避免CSRF攻击)
    HTTP请求头有个Referer字段,用于记录请求的来源。可以添加个请求拦截器,若不是来自规定页面的请求,服务器则会拒绝(用户正常发起请求的源地址与黑客冒充用户身份发起请求的源地址是不一样的)。
    但这种方法不能完全保证避免CSRF攻击,因为有些浏览器的HTTP请求头中的字段是可以篡改的,黑客可能通过篡改Referer字段伪造成合法的请求源地址,从而避开请求拦截器的拦截。
    在这里插入图片描述
  4. Anti CSRF Token(大多数人的选择)
    以前用户的信息存在Cookie中,黑客可以利用Cookie存储的用户信通过安全验证。为避免这种情况,可以用token代替Cookie中存储的用户信息,token在用户登入时由服务器下发,这个token是服务器随机生成的,并设定了有效期。客户端发送的请求都会携带在HTTP的头信息的token字段中,token用于验证用户。服务端接收到请求时,其请求拦截器会验证token是否正确,错误则拦截这次请求
    在这里插入图片描述
  5. 自定义Header中的字段
  6. Cookie的sameSite属性设置
    SameSite 是一个 cookie 属性(类似于 HTTPOnly、Secure 等),旨在缓解 CSRF 攻击。它在 RFC6265bis 中定义。此属性可帮助浏览器决定是否将 Cookie 与跨站点请求一起发送。此属性的可能值为 Lax | Strict | None
    Strict 值将阻止浏览器在所有跨站点浏览上下文中将 cookie 发送到目标站点,即使遵循常规链接也是如此。例如,对于类似 GitHub 的网站,这意味着如果登录用户点击了在公司论坛或电子邮件上发布的私有 GitHub 项目的链接,GitHub 将不会收到会话 cookie,并且用户将无法访问该项目。但是,银行网站不希望允许从外部网站链接任何交易页面,因此 Strict 标志是最合适的。

默认的 Lax 值为希望在用户从外部链接到达后维护用户登录会话的网站在安全性和可用性之间提供了合理的平衡。在上面的 GitHub 场景中,当跟踪来自外部网站的常规链接时,将允许会话 cookie,同时在 CSRF 倾向性请求方法(如 POST)中阻止它。只有在宽松模式下允许的跨站点请求才是具有顶级导航的请求,并且也是安全的 HTTP 方法。

Set-Cookie: JSESSIONID=xxxxx; SameSite=Strict
Set-Cookie: JSESSIONID=xxxxx; SameSite=Lax

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1358638.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2.0.0 BGP高级特性-ASFilter、CommunityFilter、ORF、对等组

Peer Group BGP对等体组 在网络中出现多台设备配置相近的情况下&#xff0c;使用对等体组可以极大的减少配置命令的输入。 与端口组类似&#xff0c;通过创建一个组&#xff0c;然后将成员添加入其中&#xff0c;可以对组中的成员进行统一的管理。 案例配置1 以AR2为例&…

博客的简介

博客的简介 大家可以把这个当做目录&#xff0c;从中选择自己需要的内容进行阅览&#xff0c;欢迎大家一键三连&#xff01;&#xff01;&#xff01;&#xff01; 话题讨论专栏 点击进入话题讨论专栏 主要文章&#xff1a; 神奇的代码——可随意修改复制页面内容 Python…

c语言:用共同体输出数据|练习题

一、题目 设置一个c语言共同体&#xff0c;并用共同体输出数据 如图&#xff1a; 二、代码图片【带注释】 三、源代码【带注释】 #include <stdio.h> #include<string.h> //定义一个共同体 union test { int i; char ch[10]; int id; }; //注意&…

无法开机报 不可恢复的错误:securityagent无法创建所要求的机制Teamviewerauthplugin:start

无法开机报 不可恢复的错误&#xff1a;securityagent无法创建所要求的机制Teamviewerauthplugin:start 初步判断很有可能是TeamViewer的某个启动项或者签名书没有&#xff0c; 导致在预加载的时候无法加载TeamViewer。 然后出现这个情况有一个前提&#xff0c;那就是你用了第三…

17周刷题(6~10)

编写int fun(char s[])函数&#xff0c;将八进制参数串s转换为十进制整数返回&#xff0c;若传入"77777"返回32767。 #include<string.h> int fun(char s[]) {int i strlen(s)-1, h 0, q 1;while (i>0) {h (s[i] - 0) * q;q * 8;i--;}return h; } …

uniapp+echarts开发APP版本教程

需求 需要在uniappecharts展示图表功能&#xff0c;是APP版本&#xff0c;不是小程序。找了好多教程都乱七八糟的&#xff0c;无法实现。以下是效果图 教程 1、安装插件 HBuilder安装echarts插件&#xff0c;插件地址如下。安装完成后在uni_modules/lime-echart文件夹下 ht…

MySQL卸载-Windows版

MySQL卸载 1. 停止Mysql服务2. 卸载Mysql相关组件3. 删除Mysql安装目录4. 删除Mysql数据目录5. 再次打开服务&#xff0c;查看是否有Mysql卸载残留 1. 停止Mysql服务 winR 打开运行&#xff0c;输入 services.msc 点击 “确定” 调出系统服务。 2. 卸载Mysql相关组件 打开控制…

基于SpringBoot+thymeleaf的养老院管理系统(Java毕业设计)

大家好&#xff0c;我是DeBug&#xff0c;很高兴你能来阅读&#xff01;作为一名热爱编程的程序员&#xff0c;我希望通过这些教学笔记与大家分享我的编程经验和知识。在这里&#xff0c;我将会结合实际项目经验&#xff0c;分享编程技巧、最佳实践以及解决问题的方法。无论你是…

ELF解析02 - linker

01里面&#xff0c;我们看到了修改后的 ls 程序在 maps 里面的布局&#xff1a; 在 01 里面&#xff0c;我们说到&#xff0c;r—p 这个段是一个 padding 段&#xff0c;但是实际上不是的。 我们一行行介绍&#xff0c;从第一行看起&#xff1a; 5fde6d4000-5fde731000 r-xp …

洗地机什么牌子最好?洗地机口碑榜

洗地机融合了吸尘、拖地、洗地和消毒功能&#xff0c;实现了一体化的清洁解决方案。它能够同时进行多种清洁动作&#xff0c;从而在一次操作中高效完成吸尘、拖地、洗地和消毒清洁任务&#xff0c;大大提高了清洁效率。但是面对面目琳琅的洗地机&#xff0c;我们该如何去挑选呢…

CDMP考试解析:从报名到成功不走弯路

❤️CDMP数据管理专业认证是由DAMA国际于2004推出&#xff0c;是一项涵盖学历教育、工作经验和专业知识考试在内的综合资格认证&#xff0c;也是目前全球wei一数据管理方面权威性认证。 &#x1f4b0;考试费用&#xff1a;CDMP的考试费用约为每科2500元。 其他可能的费用&#…

C语言KR圣经笔记 5.7多维数组 5.8指针数组初始化 5.9指针vs多维数组

5.7 多维数组 C 提供了矩形的多维数组&#xff0c;虽然实际上它们用得比指针数组少得多。本节我们将展示多维数组的一些特性。 考虑下日期转换的问题&#xff1a;把某月的第几天转换为当年的第几天&#xff0c;以及反向转换。例如&#xff0c;3月1日是非闰年的第60天&#xf…

CG Magic分享3d max渲染效果图时,不可忽略的灯光技巧!

一幅效果图是否能够呈现更完美&#xff0c;不止是完美的模型基础&#xff0c;而且灯光的设置也不能忽视。 尤其&#xff0c;对于3dmax室内灯光渲染还是很重要的&#xff0c;对于新手伙伴来说&#xff0c;可能会想到的3dmax怎么打灯渲染&#xff1f; 3dmax灯光渲染设置需要注意…

CSS基础笔记-01CSS概述

文章目录 前言CSS是什么CSS的作用CSS语法添加CSS的方法 前言 CSS是什么&#xff1f;有什么作用&#xff1f;怎么编写CSS&#xff1f;怎样添加CSS&#xff1f;本文对CSS的四个方面作了学习并形成学习笔记。 CSS是什么 CSS &#xff08;Cascading Style Sheets&#xff0c;层叠…

vite环境变量的坑

最近在写项目的时候&#xff0c;遇到这么一个bug。直接看图&#xff1a; 这是我启动项目的时候vscode的提示&#xff1a; 然后默认自动打开浏览器 是不是发现bug了。你们绝对想不到这个bug是什么。我直接说吧。 这个bug来着一个环境变量&#xff0c;这个变量用来配置是否默认…

Mac 软件出现「意外退出」及「打不开」解决方法

Mac 软件出现「意外退出」及「打不开」解决方法 软件出现意外退出及软件损坏的情况&#xff0c;这是因为苹果删除了TNT的证书&#xff0c;所以大部分TNT破解的Mac软件会出现无法打开&#xff0c;提示意外退出。 终端需先安装Xcode或Apple命令行工具 如未装Xcode可以使用下列命…

SWM341系列之86盒智能开关应用

SWM341系列 86盒智能开关应用 华芯微特SWM341系列的SWM34SRET6&#xff0c;在86盒智能开关产品中的应用。 SWM34SRET6性能和UI的描述 SWM34SRET6是一款基于ARM Cortex-M33内核&#xff0c;最高主频可达150MHz时钟&#xff0c;提供内置512KB Flash&#xff0c;64KB SRAM&#…

给出一句话来描述想要的图片,就能从图库中搜出来符合要求的

介绍 地址&#xff1a;https://github.com/mazzzystar/Queryable The open-source code of Queryable, an iOS app, leverages the OpenAIs CLIP model to conduct offline searches in the Photos album. Unlike the category-based search model built into the iOS Photos…

js逆向第8例:猿人学第1题-js 混淆-源码乱码

题目1:抓取所有(5页)机票的价格,并计算所有机票价格的平均值,填入答案。 老规矩打开控制台调试,出现debugger 过掉这个很简单了,右键点击“一律不在此处暂停” 这样就可以查看具体的网络请求如下: m是加密值,熟悉的大佬能发现这串加密字符非常像md5,|后面的就是时…

linux 浅练一下哈

1.新建用户test不建家目录不允许登录&#xff0c;uid为10086_____________________ useradd -u 10086 -M -s /sbin/nologin 2.将 /opt 文件夹中所有文件的属主&#xff0c;属组改成&#xff0c;test_______________________ chown -R test.test /opt chown -R …