【Debug】 你所知道的Console - API---第7天

Debug JavsScript的时候最简单直觉的方式就是console.log,不过除了log以外,Console API其实还有非常多好用的Method,来看看Console家族中有哪些厉害的成员吧。

Console API

大部分的时候console.log都能解决问题,不过用对Method可以省去更多时间。

console.assert
它的作用和console.log差不多,最大的差别是当第一个参数是falsy时才会作用。

[false, null, undefined, 0, -0, 0n, NaN, ""]

为了检查user物件的name属性有没有问题,可能会写出以下的程式码来Debug:

const user = {
    
    
  name: ""
};
if (!user.name) {
    
    
  console.log('哪邊出錯了QQ', user);
}

这种状况使用console.assert就不需要另外加入if判断式,不但写了更少程式码,在语意上也很清晰:「条件不符就抛错。」:

console.assert(user.name, '哪邊出錯了QQ', user);

在这里插入图片描述
唯一要注意的就是第一个参数必须是falsy值才会出现error,条件写反了什么事情都不会发生。

console.count

console.count(label)会印出这个标签被执行了几次,预设值是default,可以用在快速的计数。

可以用以下的程式码试试console.count的效果:

function count(arg) {
    
    
  console.count(arg);
}
count('foo');
count('bar');
count('bar');

也能用来检查多种状况的出现次数:

for (let i = 0; i < 5; i++) {
    
    
  const int = Math.ceil(Math.random() * 100);
  if (int < 20) console.count('太高了');
  if (int > 20) console.count('太低了');
}

在这里插入图片描述
console.countReset
与count相生,用来归零,可用在计算单次行为的触发的计数,例如想在React中计算按下按钮后总共触发了几次Render。

同步的状况下Event handler内的setState会被React Batch在一起,但非同步时每个setState都会触发Render,因此以下范例在点击按钮后会触发3次Render。

function App() {
    
    
  const [count, setCount] = React.useState(0);
  const [count2, setCount2] = React.useState(0);
  const [asyncCount, setAsyncCount] = React.useState(0);
  const [asyncCount2, setAsyncCount2] = React.useState(0);
  const onClick = () => {
    
    
    console.countReset('render'); // 計算前先把 'render' 歸零
    setCount(count + 1); // 1
    setCount2(count2 + 1); // 1
    Promise.resolve().then(() => {
    
    
      setAsyncCount(asyncCount + 1); // 2
      setAsyncCount2(asyncCount2 + 1); // 3
    })
  }
  console.count('render');
  return (
    <div onClick={
    
    onClick}>
      <h1>Hello, please click me.</h1>
      <h2>{
    
    count}</h2>
    </div>
  );
}

在这里插入图片描述

console.group

为了在一大堆混乱的讯息中一眼看到自己的log,是否曾经写出这样的程式码呢?

console.log('---------');
console.log(object);
console.log('---end---');

虽然—是很显眼没错,但其实有更好的做法,用console.group可以自订Message group的标签也可以多层嵌套,并用console.groupEnd来关闭Group:

console.group('Start debugging');
console.log('de-');
console.group('Nested');
console.warn('deeper message');
console.groupEnd();
console.log('bug');
console.groupEnd();

在这里插入图片描述
另外还有Group的兄弟console.groupCollapsed,只差在预设Gourp是闭合的需要手动展开。

console.table

如果在这些Console API中只能选一个来介绍,那肯定是console.table,笔者自己就常常用到它。

需要印出阵列中的物件时,比起直接用console.log印出再慢慢展开,console.table绝对是更好的选择,来看看以下范例。

const rows = [
  {
    
    
    "name": "Frozen yoghurt",
    "calories": 159,
    "fat": 6,
    "carbs": 24,
    "protein": 4
  },
  {
    
    
    "name": "Ice cream sandwich",
    "calories": 237,
    "fat": 9,
    "carbs": 37,
    "protein": 4.3
  },
  {
    
    
    "name": "Eclair",
    "calories": 262,
    "fat": 16,
    "carbs": 24,
    "protein": 6
  }
];

直接执行console.log(rows)会发生什么事情呢?

在这里插入图片描述
这绝对不会是Debug时想要看到的东西,需要手动展开物件才能看到内容,如果按住Option或Alt来一次展开全部属性呢?

在这里插入图片描述
只能展开第一个物件,而且把__proto__都给展开了,试试 console.table(rows)会印出什么结果:

在这里插入图片描述
相较console.log直接印出物件本身,console.table会以表格来印出物件内容,一次显示更多资讯,另外可以用参数改变显示的栏位以及拖拉调整栏位的宽度。

console.table(rows, [‘name’, ‘fat’]);

除了显示上更为清楚外,console.table还解决了另一个问题,试试在Console中执行以下代码,首先宣告一个物件animal,以console.log印出后再修改物件的属性:

const animal = {
    
    
  name: 'mimi',
  type: 'cat',
  other: {
    
    
    emoji: '?',
    sound: 'meow'
  }
};
console.log(animal);
animal.name = 'ami';

执行后会再手动展开物件出现以下结果:

在这里插入图片描述
可以看到展开前后的name属性值是不同的,由于执行console.log的当下还没修改animal的内容,正确显示了执行 console.log当下的物件值,也是一般预期想看到的值,但手动展开物件的时候值已经改变了,而使用console.table的话正好能避开这种困惑的情况。在这里插入图片描述
不过这样的行为其实不是个问题,执行console.log时右上角会有一个小图示,Hover上去会看到提示Value below was evaluated just now.,说明了看到的是展开当下物件的值。

同场佳映:当物件内容较深的时候,JSON.stringify(animal, null, 2)也是不错的选择,直接将物件转为JSON字串全部显示。
在这里插入图片描述
console.time
想要测量如使用者行为或是Function 执行的时间的话,很常看到一种方式-- 算数学:

const t0 = performance.now();
alert('Hello World!');
const t1 = performance.now();
alert('Another Hello World!');
console.log(`Spent: ${
    
    t1 - t0} ms`);
const t2 = performance.now();
console.log(`Spent: ${
    
    t2 - t0} ms`);

想要快速测试时间还写了这堆程式码实在有点恼人,用console.time来改写一下,和console.group一样可以传入标签参数来识别计时器:

console.time('Spent');
alert('Hello World!');
console.timeLog('Spent');
alert('Another Hello World!');
console.timeEnd('Spent');

在这里插入图片描述
用法非常简单,用time启动计时器后可用无限个timeLog来印出目前过了多久时间,最后用timeEnd来停止计时器,如果在timeLog或timeEnd中放入未启动的标签会喷Warning。

在这里插入图片描述

console.trace

如果出问题的部分和其他套件有关系,尤其是一个Function会在多处被使用的时候,有别于console.log只能得知执行当下程式码的位置,console.trace会印出Call stack并直接展开,能更快速看出问题:

function a() {
    
    
  console.trace();
}
function b() {
    
    
  a();
}
function c() {
    
    
  b();
}
b()
c()

在这里插入图片描述
笔者曾经在使用影片播放器套件的时候,不知道是不是自己写坏了,有时影片会突然暂停,那时就用了类似以下的程式码来检查,马上就看出是套件中某个Function触发了暂停。

video.addEventListener('pause', console.trace);

小结

今天讲解的Console API 有许多个都是笔者爱用的Debug 方式,确实节省了不少时间呢,明天将会讲解可在Console 面板中使用,但不属于Console API 的内建Debug Function。

猜你喜欢

转载自blog.csdn.net/wlcs_6305/article/details/115009513
今日推荐