20240229笔记

浏览器预加载器

手动:prefetch preload

<link rel="prefetch" href="next.html"> 
<link rel="preload" as="style" href="styles.css">
<link rel="preload" as="javascript" href="1.js">  

会尽早加载但不会过早执行script
自动:浏览器自身的智能预测和预先加载下一页内容的功能。浏览器内部策略决定。

动态加载脚本
通过script标签实现
缺点:对浏览器预加载器是不可见的

https2优点

  1. 多路复用
  2. 二进制分帧
  3. 头部压缩
  4. 服务器推送
  5. 优先级和流量控制

下载图片并不一定要将image添加到dom中,只要添加了src就会下载。
下载Js需要添加src,并添加到dom中。

load事件和DOMContentLoaded事件的区别

load:整个页面的所有资源已完成加载后触发。
DOMContentLoaded:HTML文档被完全加载和解析完成时触发,不用等样式表、img、js、其他资源加载完毕。在load之前触发。

代理模式的作用

1.跟踪属性的访问,设置get set函数,来跟踪什么时候去获取属性,什么时候设置属性,并进行拦截
2.隐藏属性,在get set函数中进行判断,来隐藏属性,外部不能访问这些属性
3.属性验证,在get set函数中,set时进行属性验证,来决定是否允许还是拒绝赋值
4.函数参数与构造函数参数的验证
在apply中,判断arguments参数的类型
在construct中,判断arguments参数的类型
5.数据绑定与可观察对象
在construct中,将所有的proxy对象添加到list集合中,再把集合通过new Proxy中的set函数,来进行事件绑定程序
代理是object的透明抽象层,代理的反射Reflect的api,封装了拦截的相对应的方法

const target = {
foo: "bar",
};const handler = {//定义一个get捕获器,在获取属性和Object.create时候会调用,在代理对象上执行操作时才会调用,在目标对象上执行操作是正常行为
get() {return "handler";
},
};
const proxy = new Proxy(target, handler);
console.log(target.foo);
console.log(proxy.foo);console.log(Object.create(target)['foo']);
console.log(Object.create(proxy)['foo']);

捕获器参数和反射api

const target = {foo:'bar'
}const handler = {//get捕获器的参数get(target,property[,receiver])get(trapTarget,property,receiver){console.log(trapTarget===target);console.log(property);console.log(receiver===proxy);return trapTarget[property];}}
const proxy = new Proxy(target,handler);
console.log(target.foo);
console.log(proxy.foo);

空代理对象:指的是使用反射Reflect的api来定义捕获器

const target = {foo:'bar'
}const handler = {//get捕获器的参数get(target,property[,receiver])// get(trapTarget,property,receiver){//     return Reflect.get(...arguments)// }//简洁的写法get:Reflect.get}const proxy = new Proxy(target,handler);//捕获所有方法,利用Reflect转发给对应反射API的空代理来实现const proxy1 = new Proxy(target,Reflect);console.log(target.foo);console.log(proxy1.foo);console.log(proxy.foo);const target = {foo:'bar',baz:'121212'
}const handler = {//get捕获器的参数get(target,property[,receiver])get(trapTarget,property,receiver){let decoration = '';if(property==='foo'){decoration='!!!';}return Reflect.get(...arguments)+decoration;//获取foo和baz属性时,显示的结果不一样}}const proxy = new Proxy(target,handler);console.log(target.foo);console.log(proxy.foo);console.log(target.baz);console.log(proxy.baz);

捕获器不变式 每个捕获的方法都知道目标对象的上下文,捕获函数签名

target的属性不可配置时,在捕获器中去修改属性会报错

  const target = {};Object.defineProperty(target,'foo',{configurable:false,writable:false,value:'bar'})const handler = {get(){return 'quz'}}const proxy = new Proxy(target,handler);console.log(proxy.a);
//   console.log(proxy.foo);

可撤销代理 Proxy.revocable方法

const target = {foo:'bar'
}   
const handler = {get(){return 'inter'}
}
const {proxy,revoke} = Proxy.revocable(target,handler);// 撤销函数和代理对象是在实例化的时候同时产生的
console.log(proxy.foo);
revoke();//撤销后,Proxy与target之间的管理取消,而且不可恢复
console.log(proxy.foo);

使用反射API

  1. 反射API与对象API
    1.反射api并不限于捕获处理程序
    2.大多数反射API在Object类型上有对应的方法
    Object上的方法适用于通用程序,反射方法适用于细粒度的对象控制与操作
  2. 状态标记:表示执行操作是否成功,return true/false
    Reflect.defineProperty()
    Reflect.preventExtensions()
    Reflect.setPrototypeOf()
    Reflect.set()
    Reflect.deleteProperty()
  3. 用一等函数替代操作符
    Reflect.get():替代属性访问操作符
    Reflect.set():替代=赋值操作符
    Reflect.has():替代in或者with()
    Reflect.deleteProperty():替代delete操作符():
    Reflect.construct():替代new操作符
  4. 安全的应用函数
    Reflect.apply(myFunc,this.val,argumentsList)

代理另一个代理

const target = {foo: "bar",
};
const firstProxy = new Proxy(target,{get(){console.log('first proxy');return Reflect.get(...arguments);}
})
const secondProxy = new Proxy(firstProxy,{get(){console.log('second proxy');return Reflect.get(...arguments);q}
})
console.log(secondProxy.foo);

代理的问题与不足

  1. this的执行问题 解决: 重新配置代理,把代理实例改为代理本身
  2. 代理与内部槽位 有些内置ECMAScript内置类型可能会依赖代理无法控制的机制,比如Date类型方法的执行依赖this值上的内部槽位[[NumberDate]],且不能通过get set来访问
const target = {thisValEqualsProxy() {return this === proxy;},
};
const proxy = new Proxy(target, {});
console.log(target.thisValEqualsProxy());//false
console.log(proxy.thisValEqualsProxy());//trueconst target = new Date();
const proxy = new Proxy(target,{});
console.log(target instanceof Date);
target.getDate();
console.log(proxy instanceof Date);
proxy.getDate();//报错

BOM

  1. window对象
  2. location 对象

获取query参数

let getQueryStringArgs = function () {//?a=1&b=2let location = {};location.search = "?a=1&b=2";let qs = location.search.length > 0 ? location.search.substring(1) : "";let args = {};//[a=1,b=2]qs.split("&").map((item) => item.split("=")).map((item) => {let name = decodeURIComponent(item[0]),value = decodeURIComponent(item[1]);name.length > 0 ? (args[name] = value) : "";});console.log(args);return args;
};let res = getQueryStringArgs();
console.log(res.c);

encodeURL encodeURIComponent

encodeURL对整个url进行编码,但是会保留某些字符不变,不会对=&编码,适用于整个URL编码
更严格的编码,会编码所有非字母数字符号,确保所有引起解析问题的字符都被正确编码,适用于URL的各个部分编码

let url = 'https://example.com/path?name=John Doe&age=30';
console.log(encodeURI(url));
console.log(encodeURIComponent(url));
let name = encodeURIComponent('j A');
let age = encodeURIComponent(30);
let query = `name=${name}&age=${age}`;
console.log(query);

URLSearchParams构造函数,来创建search实例,实例有set get delete has方法,且实例是迭代对象

const s= new URLSearchParams('?a=1&b=2');
console.log(s.get('a'));
s.set('c',3);
console.log(s.has('a'))
s.delete('a');

navigator对象 浏览器对象

history

history.pushState() history.replaceState() popstate事件

客户端检测

  1. 能力检测:在js运行时中使用一套简单的检测逻辑,测试浏览器是否支持某种特性。
    基于能力检测进行浏览器分析:
    1. 检测特性
    2. 检测浏览器
    3. 能力检测的局限:适合用于决定下一步该怎么做,不一定能够作为辨识浏览器的标志。
  2. 用户代理检测:通过浏览器的用户代理字符串确定使用的是什么浏览器。用户代理字符串包含在每个http请求的头部。
    navigator.userAgent
    1. 伪造用户代理
    2. 分析浏览器
  3. 软件与硬件检测
    navigator.vendor 浏览器开发商信息
    navigator.platform 浏览器所在的操作系统
    screen.colorDepth screen.pixelDepth 设备中每像素用于显示颜色的位数
    screen.orientation 屏幕信息
    浏览器元数据
    1. Geolocation API
      navigator.geolocation.getCurrentPosition()获取position对象
    2. connection state和NetworkInformation API
      navigator.online
      online事件和offline事件
      navigator.connection 连接对象
      navigator.connection.onchange事件
    3. Battery Status API
      navigator.getBattery().then().catch()
    4. 硬件
      1. navigator.hardwareConcurrency:处理器核心数,不一定是实际的CPU核心数,而是表示浏览器可以并行执行的最大工作线程数量。
      2. navigator.deviceMemory:设备内存大小,>8时还是显示为8。
      3. navigator.mediaDevices:获取设备最大触摸点数。

DOM:文档对象模型

是W3C制定的一系列接口和协议,用于标识XML或HTML文档的结构,允许开发者通过js等脚本语言动态访问和操作网页内容

  1. DOM 1:document.createElement() document.getElementById() node.appendChild()
  2. DOM 2:增加了对css样式操作的支持element.style,遍历文档树NodeIterator,TreeeWalker接口,事件处理模型addEvenetListener(),removeEventListener()
  3. DOM 3:DOMParser XMLSerializer,命名空间,DocumentType,Notation,Entity等节点接口,文本范围操作,完善选择器API,允许使用css选择器来查找元素

DOM:节点层级

document:根节点
元素:html文档元素,为根节点的唯一子节点
DOM中有12种节点类型,这些类型都继承一种基本类型

  1. Node类型
     Node.ElEMENT_NODE(1)someNode.nodeType==Node.ELEMENT_NODE
   1. nodeName与nodeValue属性2. 节点关系:每个节点都有childNodes属性,为一个NodeList的实例,是一个实时的活动对象。一个节点不会在文档中有两个位置。length,hasChildNodes(),firstChild,lastChild,previousSibling,nextSibling,patentNode3.操作节点:appendChild(),insertBefore(),replaceChild(),removeChild(),cloneNode(false/true表示深复制还是浅复制)
  1. Document类型:文档对象document是HTMLDocument的实例。
    文档子节点:
     document.documentElement //htmldocument.body //bodydocument.doctype //doctype
    
    文档信息
     document.titledocument.URLdocument.domaindocument.referrer
    
    定位元素
      document.getElementById()document.getElementByTagName()  document.getElementByTagName('div')['value']即为document.getElementByTagName('div').namedItem('value')document.getElementByTagName('*')document.getElementsByName()
    
    文档写入
      document.write() //在window.onload之后write则会覆盖全Htmldocument.writeIn()document.open()document.close()
    
3. Element类型```javascriptdiv.nodeType //1div.tagName==div.nodeName//truediv.iddiv.titlediv.classNamediv.datasetdiv.getAttribute('class')//getAttribute用于取得自定义属性的值div.getAttribute('id')div.getAttribute('title')div.getAttribute('xx')div.setAttribute(key,value)//设置属性div.abcd=value//通过此种方法设置的属性无法通过getAttribute获取div.removeAttribute(key)div.attributes//是一个NamedNodeMap实例div.attributes.getNamedItem(name)div.attributes.removeNamedItem(name)div.attributes.setNamedItem(node)div.attributes.getNamedItem('id').nodeValue//返回的是id的值div.attributes['id'].nodeValue//返回的是id的值div.attributes['title'].nodeValue='1'//设置title的值为1document.createElement('div')element.childNodes```
4. Text类型```javascriptdiv.nodeType //3div.appendData(text)div.insertData(offset,text)div.deleteData(offset,count)div.replaceDate(offset,count,text)div.splitText(offset)div.substringData(offset,count)div.lengthdocument.createTextNode(text)element.normalize()//规范化文本节点,即合并两个相邻文本节点```
5. Comment类型```javascriptdiv.nodeType //8div.data//为注释的文字document.createComment('这是注释')```
6. CDATASection类型
7. DocumentType类型```javascriptdiv.nodeType //10document.doctype//<!DOCTYPE html>document.doctype.name//html```
8. DocumentFragment类型```javascriptdiv.nodeType //11document.createDocumentFragment()```
9. Attr类型```javascriptdiv.nodeType //2let attr = document.createAttribute('align')attr.value="left"element.setAttributeNode(attr)element.attributes['align'].value//leftelement.getAttributeNode('align').value//leftelement.getAttribute('align')//left//推荐使用getAttribute() removeAttribute() setAttribute()来操作属性```

DOM编程

  1. 动态脚本
    document.createElement('script')
    
  2. 动态样式
     document.createElement('link')
    
    NodeList是基于DOM文档的实时查询,使用时需缓存NodeList
  3. MutationObserver接口,可观察的范围包括属 性变化、文本变化和子节点变化。可添加观察范围的白名单。
    使用:
     let observer = new MutationObserver(()=>console.log('change'))observer.observe(document.body,{attributes:true})
    
    回调与MutationRecord
    let observer = new MutationObserver((mutationRecords,mutationObserver)=>console.log(mutationRecords,mutationObserver));
    observer.disconnect()//提前终止执行回调,一刀切。终止后可重新关联
    observer.observe(childA,{attributes:true});
    observer.observe(childB,{attributes:true});//observer可复用
    
  4. MutationObserverInit与观察范围:
    1. 观察属性
      attributes:true //所有的属性
      attributeFilter:[‘foo’]//白名单
      attributeOldValue:true//是否保存旧值
    2. 观察字符数据:Text Comment 的添加、删除和修改
      characterData:true
      characterDataOldValue:true
    3. 观察子节点
      childList:true
    4. 观察子树
      subtree:true
  5. 异步回调与记录队列:每个队列对每一个mutationObserver实例都是唯一的,是所有DOM变化事件的有序列表
    记录队列:回调执行后,MutationRecord用不到了,记录队列会被清空,内容会被丢弃
    takeRecords:
      let observer = new MutationObserver((mutationRecords, mutationObserver) => {console.log(mutationRecords, mutationObserver);});observer.observe(document.body,{attributes:true});document.body.className='a';document.body.className='b';document.body.className='c';console.log(observer.takeRecords());//返回所有的MutationRecords实例,并清空 记录队列//observer.takeRecords();//希望断开与目标对象的联系,但又希望处理由于调用disconnect()而被抛弃的记录队列中的MutationRecord实例console.log(observer.takeRecords());
    
  6. 性能、内存与垃圾回收
    1. MutationObserver的引用
      MutationObserver实例与目标节点之间的引用关系是非对称的。
      MutationObserver对目标节点是弱引用,不会妨碍垃圾回收程序回收目标节点。
      目标节点对MutationObserver是强引用,目标节点被删除被回收,则MutationObserver也会被垃圾回收。
    2. MutationRecord的引用
      每个MutationRecord至少包含对已有DOM节点的一个引用。记录队列和回调处理的默认行为是耗尽这个队列,并被回收。建议从MutationRecord中抽取最有用的信息并保存在新对象中,最后抛弃MutationRecord。

重绘和回流

  1. 重绘:dom外观变化,但不影响其在文档流中的位置时,需要重绘。修改颜色、背景色、border样式等视觉属性,会重绘dom及其子元素的像素,不会改变页面布局。
    重绘比回流快,只涉及视觉层面的更新。
  2. 回流:回流也称为布局或重排。DOM的position、size、display变化时,需要重新计算dom的布局、宽高等,并可能导致其他dom的position变化,触发回流。
    回流操作代价大,浏览器要重新计算受影响的dom的几何信息和相关节点,可能引发后续的重绘。
    触发回流的操作:add/delete dom、修改width/height/fontSize/margin/padding等影响布局的熟悉,window的resize等。

优化网页性能,尽量减少不必要的重绘和回流:

  1. 动态需要更改的样式,尽量使用css类进行批量修改而非直接操作style属性。
  2. 将涉及布局的样式改动集中在一起一次性更新,而不是频繁的分散修改。
  3. 使用css3硬件加速特性来提升渲染性能。如transform/opacity/will-change/backface-visibility/position:fixed||sticky/composite

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

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

相关文章

调试工具vue,react,redux

React Developer Tools Redux DevTools Vue devtools 使用浏览器官方组件扩展搜索安装

C语言练习:(力扣645)错误的集合

题目链接&#xff1a;645. 错误的集合 - 力扣&#xff08;LeetCode&#xff09; 集合 s 包含从 1 到 n 的整数。不幸的是&#xff0c;因为数据错误&#xff0c;导致集合里面某一个数字复制了成了集合里面的另外一个数字的值&#xff0c;导致集合 丢失了一个数字 并且 有一个数字…

枚举和联合(共用体)

目录 枚举枚举类型的定义枚举的优点 联合&#xff08;共用体&#xff09;联合类型的定义联合的特点联合大小的计算 枚举 枚举顾名思义就是一一列举&#xff0c;把可能的取值一一列举 枚举类型的定义 enum Day &#xff0c; enum Sex &#xff0c;enum Color 都是枚举类型{}中…

springboot生成图片验证码(借鉴并分析)

目录 一、CaptchaUtil代码展示二、CaptchaController 代码展示 一、CaptchaUtil代码展示 package com.minster.yanapi.utils;import com.google.code.kaptcha.impl.DefaultKaptcha;import com.google.code.kaptcha.util.Config; import org.springframework.context.annotatio…

MMDetection3D v1.3.0安装教程

MMDetection3D v1.3.0安装教程 1. 系统环境2. 安装2.1 基本环境安装2.2 调整具体版本2.3 验证2.4 安装MinkowskiEngine和TorchSparse 3. 最终环境配置 根据 v1.3.0版本官方手册测试后的安装配置&#xff0c;亲测可行。 1. 系统环境 项目版本日期Ubuntu18.04.06 LTS-显卡RTX 2…

曾桂华:车载座舱音频体验探究与思考| 演讲嘉宾公布

智能车载音频 I 分论坛将于3月27日同期举办&#xff01; 我们正站在一个前所未有的科技革新的交汇点上&#xff0c;重塑我们出行体验的变革正在悄然发生。当人工智能的磅礴力量与车载音频相交融&#xff0c;智慧、便捷与未来的探索之旅正式扬帆起航。 在驾驶的旅途中&#xff0…

安装 Distribution Registry

Distribution Registry是由容器部署&#xff0c;所有前提是需要安装docker 参考文档&#xff1a;https://docs.docker.com/engine/install/centos/ Registry 官网文档 https://distribution.github.io/distribution/ 安装Registry仓库 docker run -d -p 5000:5000 --restartalw…

通过css修改video标签的原生样式

通过css修改video标签的原生样式 描述实现结果 描述 修改video标签的原生样式 实现 在控制台中打开设置&#xff0c;勾选显示用户代理 shadow DOM&#xff0c;就可以审查video标签的内部样式了 箭头处标出来的就是shodow DOM的内容&#xff0c;这些内容正常不可见的&#x…

MySQL 用了哪种默认隔离级别,实现原理是什么?

MySQL 的默认隔离级别是 RR - 可重复读&#xff0c;可以通过命令来查看 MySQL 中的默认隔离级别。 RR - 可重复读是基于多版本并发控制&#xff08;Multi-Version Concurrency Control&#xff0c;MVCC &#xff09;实现的。MVCC&#xff0c;在读取数据时通过一种类似快照的方…

视觉三维重建colmap框架的现状与未来

注&#xff1a;该文章首发3D视觉工坊&#xff0c;链接如下3D视觉工坊 前言 众所周知&#xff0c;三维重建的发展已经进入了稳定期&#xff0c;尤其是离线方案的发展几乎处于停滞期&#xff0c;在各大论刊上也很少见到传统sfmmvs亮眼的文章。这也不难理解&#xff0c;传统的多视…

MYSQL 解释器小记

解释器的结果通常通过上述表格展示&#xff1a; 1. select_type 表示查询的类型 simple: 表示简单的选择查询&#xff0c;没有子查询或连接操作 primary:表示主查询&#xff0c;通常是最外层的查询 subquery :表示子查询&#xff0c;在主查询中嵌套的查询 derived: 表示派…

【王道数据结构】【chapter8排序】【P360t2】

试编写一个算法&#xff0c;使之能够在数组L[1……n]中找出第k小的元素&#xff08;即从小到大排序后处于第k个位置的元素&#xff09;&#xff08;可以直接采用排序&#xff0c;但下面的排序的代码只是为了方便核对是不是第k小的元素&#xff0c;k从0开始计算&#xff09; #in…

出海手游收入一路高歌,营销上如何成功?

出海手游收入一路高歌&#xff0c;营销上如何成功&#xff1f; 以RPG和SLG为代表的中重度游戏一直是国内厂商在海外市场的传统优势品类&#xff0c;因为它们具有较高的投资回报率&#xff0c;是国内厂商在国际市场上取得成功的“吸金”利器。 据伽马数据发布的《2023全球移动游…

SpringCloud搭建微服务之Consul服务配置

1. 概述 前面有介绍过Consul既可以用于服务注册和发现&#xff0c;也可以用于服务配置&#xff0c;本文主要介绍如何使用Consul实现微服务的配置中心&#xff0c;有需要了解如何安装Consul的小伙伴&#xff0c;请查阅SpringCloud搭建微服务之Consul服务注册与发现 &#xff0c…

steam怎么付款

信用卡支付 登录Steam账户&#xff0c;选择需要购买的游戏或其他物品&#xff0c;点击“加入购物车”。在购物车页面点击“去结账”按钮&#xff0c;进入付款页面。在付款页面选择信用卡付款方式&#xff0c;填写信用卡信息&#xff0c;输入验证码&#xff0c;点击确认付款。 …

Servlet 新手村引入-编写一个简单的servlet项目

Servlet 新手村引入-编写一个简单的servlet项目 文章目录 Servlet 新手村引入-编写一个简单的servlet项目一、编写一个 Hello world 项目1.创建项目2.引入依赖3.手动创建一些必要的目录/文件4.编写代码5.打包程序6.部署7.验证程序 二、更方便的处理方案&#xff08;插件引入&am…

autocrlf和safecrlf

git远程拉取及提交代码&#xff0c;windows和linux平台换行符转换问题&#xff0c;用以下两行命令进行配置&#xff1a; git config --global core.autocrlf false git config --global core.safecrlf true CRLF是windows平台下的换行符&#xff0c;LF是linux平台下的换行符。…

98 greenplum 集群搭建过程中碰到的几个问题

前言 最近有搭建 greenplum 集群的需求 然后 在搭建的过程中碰到了一些问题, 还是有一些时间开销 并且问题也稍微有些复杂, 因此记录一下 1. Do not have enough valid segments to start the array. 报错日志信息如下 20220408:14:15:29:021638 gpstart:gp1:gpadmin-[I…

基于springboot+vue的公交线路查询系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

Find My运动相机|苹果Find My技术与相机结合,智能防丢,全球定位

运动相机设计用于在各种运动和极限环境中使用&#xff0c;如徒步、登山、攀岩、骑行、滑翔、滑雪、游泳和潜水等&#xff0c;它们通常具有防抖防震、深度防水和高清画质的特点&#xff0c;能够适应颠簸剧烈的环境&#xff0c;甚至可以承受一定程度的摔落&#xff0c;一些运动相…