encodeURI () vs. encodeURIComponent ()

Eu costumava pensar que essas duas funções JavaScript faziam a mesma coisa: codificar caracteres especiais em uma string de URL para que pudesse ser usada com segurança para fazer uma solicitação HTTP.

Acontece que eu estava perdendo o ponto: encodeURI () irá codificar uma string de URL, mas não os parâmetros ou hash . Então:

encodeURI("http://www.google.com/results with spaces#some-anchor")

retorna:

http://www.google.com/results%20with%20spaces#some-anchor

Enquanto encodeURIComponent () na mesma string retornará:

http%3A%2F%2Fwww.google.com%2Fresults%20with%20spaces%23some-anchor

O que realmente queremos para um URL bem formado é chamar encodeURI () no URL base:

encodeURI("http://www.google.com/results with spaces")
http
://www.google.com/results%20with%20spaces

E encodeURIComponent () no hash:

encodeURIComponent("#some-anchor")
%23some-anchor

Compreendi meu erro graças a esta excelente resposta do SO: http://stackoverflow.com/a/3608791/363813 .

http://www.w3schools.com/jsref/jsref_encodeuri.asp indica que encodeURI () codifica caracteres especiais, exceto:, /? : @ & = + $ # (Use encodeURIComponent () para codificar esses caracteres).