Even though there is some difference between '.' and 'text()', in the example you have specified, it cannot be explained.
Consider the below html code. Here, there is no differnce between using the two.
<html>
<a>Ask Question</a>
</html>
('//a[.="Ask Question"]') and ('//a[text()="Ask Question"]') will return exactly the same result.
But then consider this html code. There will be a difference in this case.
<html>
<a>Ask Question<other/>
</a>
</html>
Since there is a child element <other> following "Ask Question", (//a[text()="Ask Question"]) will still return the <a> element, but (//a[.="Ask Question"]) will not return anything.
That's because the meaning of the two predicates (everything between [ and ]) is different. [text()="Ask Question"] will return true if any text node in that element contain exactly "Ask Question". However, [.="Ask Question"] will return true if the string value of an element is identical to "Ask Question".