How does React’s useCallback read the variable in closures

In the following example, when the button is clicked, cb2 uses the memoized function. However, why doesn’t cb2 use the first render closures (countVal: 0)?

function TestHook() {

  const [count, setCount] = useState(0)
  let countVal = 0

  const cb = useCallback(() => {
    console.log('cb dep [count]', count, countVal)
  }, [count])

  const cb2 = useCallback(() => {
    console.log('cb2 dep []', count, countVal)
  }, [])

  useEffect(() => {
    cb() // first time: 0, 0 second time: 1, 0 
    cb2() // first time: 0, 0 second time: 0, 1
  })

  const add = () => {
    console.log('add', count)
    countVal ++
    setCount(count + 1)
  }

  return (
    <>
      <button onClick={add}>add</button>
    </>
  );
}

Question:
Can anyone explain the result of cb2() after a re-render?