懒人的代码片段

整理了一下常用的代码片段,需要快速定位问题时,我就会用上这些代码片段。

可以先看一下右侧的目录,再跳转自己需要的部分,并不是开发者工具不能解决问题,这些都是经验的积累,可以方便快速的定位问题,仅供参考。

寻找页面滚动元素

开发了一个横向展示的banner,鼠标移动到上面时,会自动展开当前卡片,折叠其他卡片。自测没问题,提交代码。

但发布测试环境发现banner出现了横向滚动条,于是拉取代码后,发现本地也必现了。但滚动条宽度非常细微。很难定位,需要出现找到滚动条出现的元素。

滚动条出现的原因是内部容器超出外部容器宽度,外部容器设置了overflow: auto/scroll;x-overflow: auto/scroll;

js 复制代码
// 把下边的代码粘贴到浏览器Console中敲回车,然后滚动界面,它会输出滚动的元素
function findScroller(element) {
    element.onscroll = function() { console.log(element)}

    Array.from(element.children).forEach(findScroller);
}

findScroller(document.body);

只要稍微操作一下,就能找到滚动的元素

假如滚动元素太多,操作不方便,还可以直接用代码找出来

ts 复制代码
function findScrollElements(selector?: string) {
  const root = selector ? document.querySelector(selector) : document.body;
  if (!root) return [];

  const results: { element: Element; horizontal: boolean; vertical: boolean }[] = [];

  function checkAndTraverse(el: Element) {
    const horizontal = el.scrollWidth > el.clientWidth;
    const vertical = el.scrollHeight > el.clientHeight;

    if (horizontal || vertical) {
      results.push({ element: el, horizontal, vertical });
    }

    // 递归遍历子元素
    el.children && Array.from(el.children).forEach(child => checkAndTraverse(child));
  }

  checkAndTraverse(root);
  return results;
}

// 使用方法
const scrollElements = findScrollElements(); // 不传选择器默认从 body 开始
scrollElements.forEach(({ element, horizontal, vertical }, index) => {
  console.log(`元素 #${index + 1}:`, element);
  console.log('横向滚动条:', horizontal);
  console.log('纵向滚动条:', vertical);
});

翻译成js版本Typescript 演练场

当然也可以用浏览器开发者工具的的Layers和Rendering选项卡,在页面上操作后,也能快速定位滚动区域。

适用场景:当开发者工具不能够定位到影响元素出现滚动的原因时。

高亮所有超出容器的元素(横向或纵向)

ini 复制代码
function highlightOverflow() {
  const all = document.querySelectorAll('*');
  all.forEach(el => {
    if (
      el.scrollWidth > el.clientWidth ||
      el.scrollHeight > el.clientHeight
    ) {
      el.style.outline = '2px dashed orange';
    }
  });
}
highlightOverflow();

适用场景:找出谁撑爆了容器、谁引发了滚动条。

从对象、JSON中查找属性、值

ts 复制代码
type Obj = Record<string, any> | any[];

interface FindResult {
  path: string;
  value: any;
  isFunction: boolean;
}

/**
 * 从对象中查找指定属性名或方法名,支持精确和模糊匹配,返回路径和值
 * @param obj 目标对象
 * @param targetKeys 属性或方法名字符串或字符串数组
 * @param fuzzy 是否模糊匹配,默认false(精确匹配)
 * @param currentPath 当前递归路径,外部调用时不传
 */
function findPathsWithValues(
  obj: Obj,
  targetKeys: string | string[],
  fuzzy = false,
  currentPath = ''
): FindResult[] {
  if (obj == null || typeof obj !== 'object') return [];

  const keysToFind = Array.isArray(targetKeys) ? targetKeys : [targetKeys];

  let results: FindResult[] = [];

  const matchesKey = (key: string) => {
    if (fuzzy) {
      return keysToFind.some(tk => key.includes(tk));
    } else {
      return keysToFind.includes(key);
    }
  }

  if (Array.isArray(obj)) {
    for (let i = 0; i < obj.length; i++) {
      const value = obj[i];
      const path = currentPath ? `${currentPath}[${i}]` : `[${i}]`;
      if (typeof value === 'object' && value !== null) {
        results = results.concat(findPathsWithValues(value, targetKeys, fuzzy, path));
      }
    }
  } else {
    for (const key of Object.keys(obj)) {
      const value = obj[key];
      const path = currentPath ? `${currentPath}.${key}` : key;

      if (matchesKey(key)) {
        results.push({
          path,
          value,
          isFunction: typeof value === 'function',
        });
      }

      if (typeof value === 'object' && value !== null) {
        results = results.concat(findPathsWithValues(value, targetKeys, fuzzy, path));
      }
    }
  }

  return results;
}

翻译成js版本Typescript 演练场

使用方法

js 复制代码
const obj = {
  fooBar: 1,
  barBaz() { return 'baz'; },
  nested: {
    fooBaz: 2,
    bazQux() { return 'qux'; },
  },
};

const exact = findPathsWithValues(obj, ['fooBar', 'barBaz']);
console.log('精确匹配:', exact);

const fuzzy = findPathsWithValues(obj, ['foo', 'baz'], true);
console.log('模糊匹配:', fuzzy);

这个依然有很多好用的工具,比如FeHelper、JSONHero,但这段代码可以在代码中调用,如果找到了值,可以添加添加debugger,可以搭配开发者工具的条件断点来调试。

还可以扩展一下,支持搜索value。

适用场景:需要在代码中调试对象中某个有某个key的情况。

利用 MutationObserver 实时监听 DOM 变化

页面有些动态插入/修改的元素,手动刷新查找不方便,用 MutationObserver 监听DOM树变化,自动输出新元素,定位问题或做调试。

ini 复制代码
const observer = new MutationObserver((mutations) => {
  mutations.forEach(mutation => {
    mutation.addedNodes.forEach(node => {
      if (node.nodeType === 1) { // 元素节点
        console.log('新元素插入:', node);
      }
    });
  });
});

observer.observe(document.body, { childList: true, subtree: true });

// 需要停止时:observer.disconnect();

适用场景:动态渲染页面,调试元素何时何地被插入。

快速打印当前组件或DOM树层级结构

页面结构复杂时,想快速看当前元素的层级结构:

javascript 复制代码
function printDomTree(el = document.body, indent = 0) {
  console.log(' '.repeat(indent * 2) + el.tagName.toLowerCase() + (el.id ? `#${el.id}` : '') + (el.className ? `.${el.className.split(' ').join('.')}` : ''));
  Array.from(el.children).forEach(child => printDomTree(child, indent + 1));
}

// 打印 body 下的DOM树
printDomTree();

适用场景:查看DOM结构,快速定位元素层级关系。

捕获并记录所有未处理的 Promise 异常

异步代码调试头疼时,用这个捕获全局未处理的 Promise 拒绝,方便快速定位报错位置。

javascript 复制代码
window.addEventListener('unhandledrejection', event => {
  console.error('未处理的Promise拒绝:', event.reason);
});

适用场景:调试异步请求失败,避免静默错误。

利用 Performance API 监测函数执行耗时

定位性能瓶颈,可以用 Performance API 计时,替代 console.time,更灵活。

javascript 复制代码
function profile(name, fn) {
  performance.mark(`${name}-start`);
  const result = fn();
  performance.mark(`${name}-end`);
  performance.measure(name, `${name}-start`, `${name}-end`);
  const measures = performance.getEntriesByName(name);
  console.log(`${name}耗时: ${measures[0].duration.toFixed(2)}ms`);
  performance.clearMarks();
  performance.clearMeasures();
  return result;
}

// 使用
profile('计算密集型任务', () => {
  // ...耗时操作
});

适用场景:精准测量任意函数执行时间,找性能瓶颈。

一键复制对象 JSON,方便快速分享调试数据

console 里打印的对象展开后复制不方便,用这个快速复制对象序列化 JSON。

javascript 复制代码
function copyJson(obj) {
  const json = JSON.stringify(obj, null, 2);
  navigator.clipboard.writeText(json).then(() => {
    console.log('已复制JSON到剪贴板');
  }).catch(() => {
    console.error('复制失败');
  });
}

// 使用
copyJson({foo: 'bar', nested: {a: 1}});

适用场景:快速导出复杂数据结构给同事,便于复现和分析。

通过 CSS Outline 给任意元素添加醒目边框定位

调试页面样式错乱,给页面任意元素临时加轮廓线,方便视觉定位。

ini 复制代码
function highlight(selector, color = 'red') {
  document.querySelectorAll(selector).forEach(el => {
    el.style.outline = `2px solid ${color}`;
  });
}

// 使用
highlight('.my-banner');

适用场景:定位复杂布局中某些元素,视觉快速排查。

明白了,你要的是真正能在前端开发中快速定位疑难杂症 的调试技巧,不是泛泛的优化建议。我这次只说硬核的、现场能救命的技巧,尤其适合以下场景:

  • 页面莫名错位 / 滚动条溢出 / 点击无效 / 样式冲突 / 动画鬼畜等
  • 不方便打断点、不知道从哪下手分析
  • 需要用非常规方式追踪问题

下面这批调试技巧,工程化 + 浏览器能力 + 元编程技巧,都能让你眼前一亮。

1. 快速可视化所有元素边框

ini 复制代码
[...document.querySelectorAll('*')].forEach(el => {
  el.style.outline = '1px solid rgba(255,0,0,0.2)';
});

排查元素错位、尺寸不对、隐藏溢出、margin collapse 等视觉问题。
也可以把颜色调成 rgba(0,255,0,0.2) 代表可见元素,便于观察嵌套结构。

找到元素被谁覆盖了(z-index 或 pointer-events 问题)

javascript 复制代码
document.addEventListener('click', function (e) {
  const topElement = document.elementFromPoint(e.clientX, e.clientY);
  console.log('你点到的实际顶层元素是:', topElement);
});

适用场景:点击事件无效 / hover 无响应 / 模态层穿透。

配合 DevTools 中的 $0(当前选中元素)可以比对是否被盖住。

快速追踪 layout/layout shift(跳动)

定位页面跳动、卡片抖动等问题,利用浏览器的 Layout Shift 调试工具

或者用代码手动打点 layout:

javascript 复制代码
new PerformanceObserver((list) => {
  list.getEntries().forEach(entry => {
    console.warn('Layout Shift:', entry);
  });
}).observe({ type: 'layout-shift', buffered: true });

打印 CSS 样式变动历史

ini 复制代码
const target = document.querySelector('#problematic-element');
const originalSetAttribute = target.setAttribute;

target.setAttribute = function (attr, value) {
  if (attr === 'style') {
    console.trace('style 被改动了:', value);
  }
  return originalSetAttribute.call(this, attr, value);
};

适用场景

Debug 动画:强制显示 transform/opacity 动画的触发点

ini 复制代码
const observer = new MutationObserver(mutations => {
  mutations.forEach(m => {
    if (m.attributeName === 'style') {
      console.log('样式变化:', m.target, m.target.style.cssText);
    }
  });
});

document.querySelectorAll('*').forEach(el => {
  observer.observe(el, { attributes: true });
});

适用场景:动画触发异常、不触发、提前触发。

实时观察 DOM 结构变化(谁插入了什么?)

javascript 复制代码
const mo = new MutationObserver(mutations => {
  mutations.forEach(m => {
    console.log('DOM变动:', m);
  });
});
mo.observe(document.body, { childList: true, subtree: true });

适用场景,不知道页面什么位置被插入了元素。

打印任意元素所有监听器(Chrome 限定)

scss 复制代码
getEventListeners($0) // $0 是 Chrome DevTools 当前选中的元素

适用场景:查看绑定元素事件。

相关推荐
前端小巷子3 分钟前
Webpack 5 新特性解析
前端·javascript·面试
90后的晨仔5 分钟前
vue中的watch 可以监听对象吗?
前端·vue.js
影子信息21 分钟前
vue3 组件生命周期,watch和computed
前端·javascript·vue.js
程序猿阿伟34 分钟前
《Angular+Spring Boot:ERP前端采购销售库存协同架构解析》
前端
90后的晨仔1 小时前
👂《侦听器(watch)》— 监听数据变化执行副作用逻辑
前端·vue.js
曾经的三心草1 小时前
微服务的编程测评系统6-管理员登录前端-前端路由优化
前端·微服务·状态模式
Point1 小时前
[LeetCode] 最长连续序列
前端·javascript·算法
rookiesx1 小时前
安装本地python文件到site-packages
开发语言·前端·python
支撑前端荣耀1 小时前
九、把异常当回事,代码才靠谱
前端
LotteChar1 小时前
HTML:从 “小白” 到 “标签侠” 的修炼手册
前端·html