performance.now()详解

performance.now() 是 JavaScript 中用于获取高精度时间戳的方法,属于 Web Performance API。它的核心特性和用途如下:


一、核心特性

特性说明
高精度精度可达 微秒级 (百万分之一秒),而 Date.now() 只有毫秒级 (千分之一秒)
单调递增时间戳只会增加,不受系统时间修改影响(即使用户修改电脑时间也不会影响结果)
相对时间起点返回的时间是相对于 页面导航开始时刻 的时间差(页面加载或浏览器 tab 首次打开)
防篡改专门用于性能测量,浏览器会阻止恶意脚本修改其行为

二、与 Date.now() 的关键区别

// 使用 Date.now()
console.log(Date.now()); // 返回从 1970-01-01 至今的毫秒数,受系统时间影响

// 使用 performance.now()
console.log(performance.now()); // 返回从页面导航开始至今的毫秒数,精度更高
对比项performance.now()Date.now()
精度微秒级 (最高 5 微秒)毫秒级
时间参考点页面导航开始时刻UNIX 纪元 (1970-01-01)
是否受系统时间影响❌ 不会✅ 会
典型用途性能分析、动画计时普通时间记录

三、经典使用场景

1. 测量代码执行时间
const start = performance.now();

// 要测量的代码
for (let i = 0; i < 1000000; i++) { 
  Math.sqrt(i); 
}

const end = performance.now();
console.log(`执行耗时: ${(end - start).toFixed(3)} 毫秒`);
2. 动画帧率计算
let lastFrameTime = performance.now();

function animate() {
  const currentTime = performance.now();
  const deltaTime = currentTime - lastFrameTime; // 计算帧间隔
  
  console.log(`当前帧率: ${1000 / deltaTime} FPS`);
  
  lastFrameTime = currentTime;
  requestAnimationFrame(animate);
}

animate();
// 创建一个 img 元素,用于在页面上显示图片
const img = document.createElement('img');

// 初始化一个变量 index,用于记录当前要显示的图片的序号,初始值为 1
let index = 1;

// 设置 img 元素的 src 属性,动态拼接图片的路径,加载序号为 index 的图片
img.src = `/src/assets/running/${index}.png`;

// 设置 img 元素的宽度为 400 像素
img.width = 400;

// 设置 img 元素的高度为 400 像素
img.height = 400;

// 将创建好的 img 元素添加到页面的 body 元素中,使其在页面上显示
document.body.appendChild(img);

// 定义动画的帧率为 30 帧每秒
let fps = 30;

// 声明一个变量 rafObj,用于存储 requestAnimationFrame 返回的请求 ID,后续用于取消动画
let rafObj;

// 使用 performance.now() 获取当前的时间戳,并赋值给 lastTime 变量,作为动画的起始时间
let lastTime = performance.now();

// 定义一个名为 animation 的函数,用于实现动画效果
const animation = () => {
    // 获取当前的时间戳
    let now = performance.now();

    // 计算当前时间与上一次更新图片的时间间隔,如果间隔大于 1000/fps(即每帧的时间间隔),则更新图片
    if (now - lastTime > 1000 / fps) {
        // 更新 lastTime 为当前时间,记录本次更新图片的时间
        lastTime = now;

        // 图片序号加 1,准备显示下一张图片
        index++;

        // 更新 img 元素的 src 属性,加载新序号对应的图片
        img.src = `/src/assets/running/${index}.png`;

        // 如果图片序号超过 12,将序号重置为 1,实现循环播放图片的效果
        if (index > 12) {
            index = 1;
        }
    }

    // 使用 requestAnimationFrame 方法请求下一帧动画,传入 animation 函数作为回调,形成动画循环
    rafObj = requestAnimationFrame(animation);
};

// 调用 animation 函数,启动动画
animation();

// 创建一个 button 元素,用于停止动画
const btn = document.createElement('button');

// 设置按钮的 id 为 'cancel'
btn.id = 'cancel';

// 设置按钮的显示文本为 '清除动画'
btn.textContent = '清除动画';

// 为按钮添加点击事件处理函数
btn.onclick = () => {
    // 使用 cancelAnimationFrame 方法取消之前通过 requestAnimationFrame 请求的动画,传入 rafObj 作为请求 ID
    window.cancelAnimationFrame(rafObj);

    // 将 rafObj 置为 null,释放资源
    rafObj = null;
};

// 将创建好的按钮添加到页面的 body 元素中,使其在页面上显示
document.body.appendChild(btn);
3. 性能基准测试
function benchmark(func) {
  const start = performance.now();
  func();
  const duration = performance.now() - start;
  return duration;
}

四、注意事项

  1. 跨域安全限制
    某些浏览器(如 Firefox)在跨域 iframe 中会降低精度以防止时序攻击

  2. 隐私保护模式
    在浏览器的隐私模式(如 Chrome 无痕模式)下可能降低精度

  3. Worker 支持
    在 Web Worker 中也可使用,但起始时间与主线程不同步

  4. 数值类型
    返回值为 DOMHighResTimeStamp 类型(实际上是 double


五、兼容性

浏览器支持版本
Chrome6+
Firefox7+
Safari8+
Edge12+
Node.js8.5+ (需通过 require('perf_hooks').performance)

六、为什么需要高精度计时?

在以下场景中微秒级精度至关重要:

  • VR/WebGL 应用的帧同步

  • 音频视频同步处理

  • 高频交易系统

  • 物理引擎计算

通过 performance.now() 开发者可以更精准地分析代码性能瓶颈。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Super毛毛穗

今天晚饭加什么?

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值