Here's the boundary-shrinking approach. Pay attention to the boundary checks before the leftward and upward passes. Without them, you'd double-count elements on single-row or single-column remaining strips.
function spiralOrder(matrix):
result = []
top = 0
bottom = matrix.length - 1
left = 0
right = matrix[0].length - 1
while top <= bottom and left <= right:
for col from left to right:
result.append(matrix[top][col])
top += 1
for row from top to bottom:
result.append(matrix[row][right])
right -= 1
if top <= bottom:
for col from right downto left:
result.append(matrix[bottom][col])
bottom -= 1
if left <= right:
for row from bottom downto top:
result.append(matrix[row][left])
left += 1
return result