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:
- It gives an incorrect result when the hash contains a non-Latin or non-alphanumeric character. For example, from the hash " # foo @ o # bar $% huh hello " it will be received simply "foo" .
- Throws a TypeError if the location.hash string is empty - because .match () returns null .
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.
- At the same test example, at least a piece of
"foo@o"
will be received, which means an approach error only when the hash contains the "#" symbol.
- When there is no hash, it does not throw an error, although it still produces undefined instead of an empty string.
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:
- From our intricate test hash, it gives the correct result: "foo @ o # bar $% huh hello"
- When there is no hash, it correctly returns an empty string.
β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! 