1 Star 0 Fork 0

Shadow / code-snippet

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
查漏补缺.md 7.90 KB
一键复制 编辑 原始数据 按行查看 历史
Shadow 提交于 2022-05-16 18:41 . 查漏补缺

Vue响应式原理

  • 1、实现一个监听器(Observer),通过Object.defineProperty劫持数据,通过设置setter、getter,能监听到获取和设置值。
  • 2、实现一个解析器(Compile),解析Vue 模板指令,将模板中的变量替换为数据,并绑定更新函数,添加数据监听的订阅者,一但数据变化,则会收到通知,然后调用更新函数。

Vue模板编译原理

  • 1、将模板编译成ast语法树(ast是用来描述语法层面的信息,比如标签、属性等)。
  • 2、将ast语法树生成字符串代码,就是和render函数一样。
  • 3、通过new Function、eval语法将字符串代码编译成函数。

网址输入到展示

  • 1、打开浏览器,输入URL
  • 2、构建请求行,查找缓存
  • 2、DNS解析,将网址解析成ip地址,因为计算机网络是基于MAC地址和IP地址进行通信的,如果是ip则不用
  • 3、完成TCP三次握手
  • 4、发送HTTP请求
  • 5、接收HTTP响应结果
  • 6、断开TCP链接,四次挥手,对于http1.1或2,不一定会断开,因为可能存在TCP链接复用的情况
  • 6、浏览器解析HTML,CSS
  • 7、构建对象模型,dom tree、layout tree,最后通过分层、栅格化,组成render tree
  • 8、浏览器渲染页面(布局)

多倍图

  • 1、直接用最大的图
  • 2、媒体查询dpr设置不同的倍率bg
  • 3、js判断dpr动态设置图片路径
  • 4、使用img的srcset属性和css的img-set函数,浏览器会自动选择srcset="/files/16864/clock-demo-200px.png 1x, /files/16797/clock-demo-400px.png 2x"background-image: -webkit-image-set( url(xxx) 1x, url(xxx) 2x, url(xxx) 600dpi);

避免重排重绘

  • 1、使用createDocumentFragment,createdocumentfragment()方法创建了一虚拟的节点对象,节点对象包含所有属性和方法。
  • 2、对于 resize、scroll 等进行防抖/节流处理。
  • 3、css will-change属性,告诉浏览器有哪些属性会发生动画,提前告诉浏览器,浏览器会进行优化。
  • 4、精简dom节点数量。
  • 5、读写分离,先获取元素的样式值,然后在进行元素的样式修改。
  • 6、使用 CSS3 中的transform,opacity属性实现动画不会经过布局和绘制,而是直接运行在合成器线程和栅格化线程中,不会受到主线程的影响。

滚动条穿透

nodejs流

  • 处理大量数据
  • 使用管道方法
  • 转换流
  • 读写流
  • 解耦I/O

事件循环

因为js是单线程,为了避免I/O阻塞,则存在事件循环机制;js为什么是单线程:避免问题变复杂,比如两个线程同时操作一个dom,浏览器就不知道以哪个线程为准。

每执行完一轮宏任务和微任务就叫做一轮事件,如此往复便是事件循环;

一轮事件循环,会执行一次宏任务,以及所有的微任务

setTimeout(() => {
  console.log('settimeout');
})
Promise.resolve().then(() => {
  console.log('promise1');
  Promise.resolve().then(() => {
    console.log('promise2');
    Promise.resolve().then(() => {
      console.log('promise3');
    })
  })
})
console.log('main');
// 输出:mian promise1 promise2 promise3 settimeout

I/O中先进先出

// 第一个先进I/O
setTimeout(() => {
  Promise.resolve().then(() => {
    console.log('promise');
  })
})
Promise.resolve().then(() => {
  // 第二个进I/O
  setTimeout(() => {
    console.log('settimeout');
  })
})
console.log('main');
// 输出:mian promise settimeout

任务队列

任务队列分为:同步任务、异步任务,避免异步任务阻塞;如遇到异步任务,则会添加到I/O(异步等待)中

  • 1、所有同步任务都在主线程执行,形成一个执行栈
  • 2、主线程外,有一个任务队列,只要异步任务有了运行结果,就会在任务队列中放置一个事件
  • 3、执行栈中同步任务执行完成,系统就会读取任务队列,看看有哪些事件,对应哪些异步任务,则结束等待,进入执行栈,开始执行
  • 4、主线程不停循环以上三步

宏任务、微任务

宏任务队列有多个,微任务队列只有一个
如果有新的异步宏任务,则会创建新的宏任务队列,然后宏任务队列会包含一个微任务队列

  • 宏任务:script(整体代码)、setTimeout、setInterval、setImmediate、I/O、UI rendering
  • 微任务:promise、process.nexTick、Object.observe、MutationObserver

nodejs事件循环

  • timers setTimeout、setInterval的回调
  • I/O callbacks 异步等待的回调函数
  • idle, prepare 系统内部的,暂不需了解
  • poll(incoming: connections, data, etc.) 异步响应回调,会存在阻塞
  • check setImmediate的回调
  • close callbacks

以上每项为事件循环的一个阶段,这6个阶段称为一轮事件循环。

I/O -> poll -> check -> timers

const fs = require('fs');
const path = require('path');
function someAsync(callback) {
  // 假设花费两毫秒
  fs.readFile(__dirname + '/' + __filename, callback);
}

const timeoutScheduled = Date.now();

let fileReadTime = 0;

setTimeout(() => {
  const delay = Date.now() - timeoutScheduled;
  console.log('setTimeout: ' + delay + 'ms have passed since i was scheduled');
  console.log('fileReadTime', fileReadTime - timeoutScheduled);
}, 10)

someAsync(function () {
  fileReadTime = Date.now();
  while (Date.now() - fileReadTime < 20) {

  }
})
// 输出:
//    setTimeout: 22ms have passed since i was scheduled
//    fileReadTime 2

// I/O -> poll -> timers
/* 
  1、setTimeout-callback、someAsync-callback进入I/O;
  2、当到达2ms,将someAsync-callback添加进poll,此时会阻塞poll;
  3、当到达22ms,会将setTimeout-callback添加进timers,再执行
  注意:因为poll的阻塞,导致setTimeout-callback原本应该在10ms后执行,结果却是22ms后执行
*/
setTimeout(() => {
  console.log('timeout');
})
setImmediate(() => {
  console.log('immed');
})
// 以上执行顺序不确定

fs.readFile('./test.js', () => {
  setTimeout(() => {
    console.log('timeout');
  })
  setImmediate(() => {
    console.log('immed');
  })
})
// 以上执行顺序:immed -> timeout

/*
  解释:
    1、因为在nodejs中setTimeout(callback, 0) === setTimeout(callback, 1),
      而浏览器setTimeout(callback, 0) === setTimeout(callback, 4);
      因为0ms是同步的;
    2、然后因为event loop启动也是需要时间的,所以有时候耗时1ms,有时候不需要1ms
*/

process.nextTick不在event loop任何阶段执行,而是在各个阶段切换的中间执行,即进入下一阶段前执行

const fs = require('fs');

fs.readFile('./test.js', () => {
  setTimeout(() => {
    console.log('setTimeout');
  })
  setImmediate(() => {
    console.log('setImmediate');
    process.nextTick(() => {
      console.log('nextTick3');
    })
  })
  process.nextTick(() => {
    console.log('nextTick1');
  })
  process.nextTick(() => {
    console.log('nextTick2');
  })
})
// nextTick1 nextTick2 setImmediate nextTick3 setTimeout
// poll(fs.readFile) -> nextTick1、nextTick2 ->check(setImmediate) -> nextTick3 -> timers(setTimeout)

闭包

定义:闭包是指有权访问另一个函数作用域中变量的函数。
产生:内部的函数存在外部作用域的引用就会导致闭包。

过程:

  • 1、每个函数执行都会创建一个新的执行上下文
  • 2、这个执行上下文有一些自己的变量
  • 3、当函数renturn时,这些变量就会被销毁

作用:

  • 保护函数的私有变量不受外部的干扰,形成不销毁的栈内存。
  • 保存,把一些函数内的值保存下来。闭包可以实现方法和属性的私有化。

应用:

  • 科利华
  • 节流、防抖
  • 函数结果缓存等等
1
https://gitee.com/ytiona/code-snippet.git
git@gitee.com:ytiona/code-snippet.git
ytiona
code-snippet
code-snippet
master

搜索帮助