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);
    }
})
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());//true

const 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=2
  let 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编码
encodeURIComponent:更严格的编码,会编码所有非字母数字符号,确保所有引起解析问题的字符都被正确编码,适用于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类型
    1. nodeName与nodeValue属性
    2. 节点关系:每个节点都有childNodes属性,为一个NodeList的实例,是一个实时的活动对象。一个节点不会在文档中有两个位置。
      length,hasChildNodes(),firstChild,lastChild,previousSibling,nextSibling,patentNode
      3.操作节点:appendChild(),insertBefore(),replaceChild(),removeChild(),cloneNode(false/true表示深复制还是浅复制)
  2. Document类型:文档对象document是HTMLDocument的实例。
    文档子节点:
     document.documentElement //html
     document.body //body
     document.doctype //doctype
    
    文档信息
     document.title
     document.URL
     document.domain
     document.referrer
    
    定位元素
      document.getElementById()
      document.getElementByTagName()   
      document.getElementByTagName('div')['value']即为document.getElementByTagName('div').namedItem('value')
      document.getElementByTagName('*')
      document.getElementsByName()
    
    文档写入
      document.write() //在window.onload之后write则会覆盖全Html
      document.writeIn()
      document.open()
      document.close()
    
  3. Element类型
    div.nodeType //1
    div.tagName==div.nodeName//true
    div.id
    div.title
    div.className
    div.dataset
    div.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的值为1
    document.createElement('div')
    element.childNodes
    
  4. Text类型
      div.nodeType //3
      div.appendData(text)
      div.insertData(offset,text)
      div.deleteData(offset,count)
      div.replaceDate(offset,count,text)
      div.splitText(offset)
      div.substringData(offset,count)
      div.length
      document.createTextNode(text)
      element.normalize()//规范化文本节点,即合并两个相邻文本节点
    
  5. Comment类型
      div.nodeType //8
      div.data//为注释的文字
      document.createComment('这是注释')
    
  6. CDATASection类型
  7. DocumentType类型
        div.nodeType //10
        document.doctype//<!DOCTYPE html>
        document.doctype.name//html
    
  8. DocumentFragment类型
       div.nodeType //11
       document.createDocumentFragment()
    
  9. Attr类型
        div.nodeType //2
        let attr = document.createAttribute('align')
        attr.value="left"
        element.setAttributeNode(attr)
        element.attributes['align'].value//left
        element.getAttributeNode('align').value//left
        element.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。

DOM扩展

  1. Selectors API
querySelector() //获取单个元素
querySelectorAll() //获取多个元素
matches()//判断元素是否匹配
  1. 元素遍历
    浏览器会把元素间的空格当做空白节点,导致childNodes和firstChild等属性上的差异。
    以下api弥补了这些差异,不用再担心空白节点:
dom.childElementCount
dom.firstElementChild
dom.lastElementChild
dom.previousElementSibling
dom.nextElementSibling
  1. HTML5 DOM扩展
    1. CSS类扩展
      getElementsByClassName()
    2. classList属性
      以前的classNames只能赋值一个类名,新增classList控制class
          dom.classList//是一个新的集合类型DOMTokenList的实例
          classList.add(value)
          classList.remove(value)
          classList.contains(value)
          classList.toggle(value)
      
    3. 焦点管理
       div.focus()
       document.hasFocus()
    
    1. HTMLDocument扩展
    	document.readyState//loading/complete
    	document.compatMode
    	document.head
    	document.characterSet
    
    1. 自定义数据属性
         div.dataset//	DOMStringMap的实例  
         div.dataset.myName  
    
    1. 插入标记
      innerHTML
      outerHTML
      ps:使用前最好手动删除要被替换的元素上关联的事件处理程序和js对象。注意跨站点脚本XSS攻击。
    2. scrollIntoView():将元素滚动到视口区域中
  2. 专有扩展
    div.children//是一个HTMLCollection,只包含元素的Element类型的子节点  
    div.contains(div1)//判断元素是否包含另一个元素  
    innerText//渲染的文本内容;textContent:去除标签的文本内容  
    outerText  
    scrollIntoViewIfNeeded()//如果元素不可见,则将元素可见 
    

DOM2和DOM3

  1. dom.style:样式属性,只能获取style设置的样式属性
  2. getComputedStyle:计算样式,能获取style上和外联的样式属性,只读
  3. document.styleSheets:操作样式表
  4. 元素尺寸
    1. 偏移尺寸:包含元素在屏幕上占用的所有视觉空间,包括内边距、 滚动条和边框(不包括margin)。只读。
     offsetWidth
       offsetHeight
       offsetLeft//相对于父元素的偏移距离
       offsetTop//相对于父元素的偏移距离
    
    1. 客户端尺寸:包含内容和padding。只读。
       document.documentElement.clientWidth//html或者body的视口尺寸的宽
       document.documentElement.clientHeight//html或者body的视口尺寸的高
    
    1. 滚动尺寸
     scrollWidth
     scrollHeight
     scrollTop
     scrollLeft
    
    1. 确定元素尺寸
      getBoundingClientRect();//DOMRect对象 
    

遍历和范围

  1. 遍历NodeIterator TreeWalker从某个起点开始执行对DOM结构的深度优先遍历
    document.createNodeIterator()
    document.createTreeWalker()
    
  2. 范围:
    document.createRange()
    

事件:

  1. 事件流:
    事件流三个阶段:事件捕获、到达目标、事件冒泡。

  2. DOM事件对象:

        event.type//事件类型 
        dom.addEventListener('click',handler)  
        dom.removeEventListener('click',handler)  
        dom.onclick=handler  
        dom.onclick=null  
        event.currentTarget//当前绑定事件的dom元素
        event.target//当前触发事件的dom元素
        this===event.currentTarget//true
        event.preventDefault()//取消默认行为的事件,比如a的跳转  
        event.stopPropagation()//立即阻止事件流在DOM结构中传播  
    
  3. 事件类型
    用户界面事件

    	  load
    	  unload
    	  resize
    	  scroll
    	  focus
    
     鼠标和滚轮事件
    
    	  click
    	  dbclick
    	  mousedown
    	  mouseenter
    	  mouseleave
    	  mousemove
    	  mouseout
    	  mouseover
    	  mouseup
    	  mousewheel
    	  event.clientX//鼠标光标在视口中的坐标
    	  event.clientY//鼠标光标在视口中的坐标
    	  event.pageX//鼠标光标在页面上的坐标
    	  event.pageY//鼠标光标在页面上的坐标
    	  event.screenX//鼠标光标在屏幕上的坐标
    	  event.screenY//鼠标光标在屏幕上的坐标
    
     修饰符
    
    	  event.shiftKey
    	  event.ctrlKey
    	  event.altKey
    	  event.metaKey
    
     鼠标按键
    
    	  event.button//按下的是鼠标主键、中键、副键
    
     鼠标滚动
    
    	  mousewheel
    	  event.wheelDelta
    
     触摸屏设备
       不支持dblclick事件
       mousemove也会触发mouseover和mouseout事件
     键盘与输入事件
    
    	  keydown//鼠标按下,按下不放,会重复触发
    	  keypress
    	  keyup//鼠标弹起
    	  event.code//按下的是哪一个健
    	  event.keyCode//按下的键的键码
    	  textInput//输入事件
    	  event.data//输入的data值
    	  event.key//键
    	  event.char
    
     HTML5事件
    
    	  DOMContentLoaded
    	  readystatechange
    	  hashchange
    

    设备事件

         orientationchange
         window.orientation
         deviceorientation
         devicemotion
    
     触摸及手势事件
    
  4. 内存与性能

    1. 事件委托优点:
      1. document对象随时可用,不用等DOMContentLoaded或load事件,只要页面渲染出可点击的元素,就可以无延迟的起作用。
      2. 节省花在设置页面事件处理程序上的时间。节省DOM引用。
      3. 减少整个页面所需的内存,提升整体性能。

    2. 删除事件处理程序
      在使用innerHTML之前清除事件dom.οnclick=null

    3. 自定义DOM事件
      CustomEvent构造函数

重绘和回流

  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

浏览器引擎

解析HTML、CSS,并根据这些内容构建和渲染页面。
浏览器引擎的主要任务:

  1. 解析与构建DOM树
  2. 样式计算与构建CSSOM树
  3. 布局与回流
  4. 绘画与重绘
  5. JS引擎交互
  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值