πŸ“œ ⬆️ ⬇️

Read hash: bulletproof method

This is probably one of those tasks that everyone thinks they know about the solution, but many solve it in the end incorrectly. Having come across one more super-weak piece of code written for this purpose, I conceived an explanatory blog entry.

The essence of the problem


You want to remove the pound symbol ( # ) from the value of location.hash . For example, when hash is "#foo" , you want to get a string containing "foo" . It's simple, right?

Difficult cases


This is what most developers seem to lose sight of: in modern, heavily najavaskriptovanyh, applications hash variable can contain any Unicode characters. It does not have to match the value of the real id attribute from the same page. And when it matches, the id attributes can now contain almost any Unicode characters . Yes, they often forget that there may not be any hash on the page. Even if the URL ends with a β€œ#” character, the string location.hash is actually "" (empty string), not "#" .
')

Naive approaches


Here is the most recent - I found it in the book, which was a technical review:

var hash = location.hash.match(/#(\w+)/)[1]; 

He has several problems at once:


I saw other variants of this approach, including using explicitly defined character classes instead of \ w , adding the beginning of the line ( ^ ) before the β€œ#” symbol (an excellent idea, contributes to performance), and checked if the .match () method returns anything before consuming its result. However, they all were usually the victims of at least one of the two problems mentioned above.

Another approach that a friend of mine used once was:

 var hash = location.hash.split('#')[1]; 

This approach also has its own problems - funny, but fewer than the previous one, although this one looks much more naive.


We get the right value


The technique I usually use is much simpler for each of the two above, and perhaps looks too weak:

 var hash = location.hash.substring(1); 

However, look more closely:


β€œBut he assumes that there is a grille at the beginning of the line !” - I can directly hear some of you exclaim. Well, it would be a real bother, if we were processing an arbitrary string. Then I would have to check if the β€œ#” character is at its beginning, and if this line exists at all. However, in the case of location.hash, this is not the case only when there is no hash. And this option is taken into account. ;)

Addition: as indicated in the comments, you can also use location.hash.slice (1) instead of substring . I like it even more, because it is shorter by 4 bytes.

If, however, you are obsessed with regeksami and wish to solve the problem with their help by all means, then this is just as bulletproof and almost as concise a way:

 var hash = location.hash.replace(/^#/, ''); 

If for some reason ( OCD ?) You want to solve a problem with .match () by all means, you can do this:

 var match = location.hash.match(/^#?(.*)$/)[1]; 

In this case, since the β€œ#” character is optional, .match () will never return null . And no, the β€œ#” symbol will never erroneously be part of the returned hash: this is how regex engines work.

β€œIt's too easy, why am I wasting my time here!”


Well, sorry. I know: for some of you this is elementary. But the guy who wrote the book is very knowledgeable (and the book is really good, except for the above-quoted code), so I thought: this means that many good developers are not right in this task, which is why it was necessary to write this blog post. If you are not one of them - rejoice in this.

β€œHey, but it's not all right!”


In this case, I would like to know what I missed - so please leave a comment! :)

Source: https://habr.com/ru/post/138314/


All Articles