I am just wondering why Uniswap use reserve and getReserves() instead of just using tokenA.balanceOf(this) and tokenB.balanceOf(this)?

Is there any reason that I do not see, like flash loans or so? (Because it is possible to call .sync() anyway... so I do not realy understand why they use this strange implementation)

Maybe someone can help me there... Thank you :)

To make it more clear:

Why Uniswap use this method:

    function getReserves() public view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast) {
            _reserve0 = reserve0;
            _reserve1 = reserve1;
            _blockTimestampLast = blockTimestampLast;
        }

And not something like:

    function getReserves() public view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast) {
                _reserve0 = token0.balanceOf(this);
                _reserve1 = token1.balanceOf(this);
                _blockTimestampLast = blockTimestampLast;
            }