Following blocks of code are similar but have different input strings and hence different results:
// This does not change HTML
var str = "%3Cdiv%3E"; // <div>
var str_dec = decodeURIComponent(str);
console.log(str_dec); // Console output is `<div>`
document.getElementById("p1").innerHTML = "1: " + str_dec; // No HTML output
// This works fine within HTML
var str = "%3C0%3E"; // <0>
var str_dec = decodeURIComponent(str);
console.log(str_dec); // Console output is `<0>`
document.getElementById("p2").innerHTML = "2: " + str_dec; // HTML output is `<0>`
<p id="p1"></p>
<p id="p2"></p>
Although, console shows that decoding works fine in first case, why it does not appear in the HTML?
This is because <0>
is not a valid HTML tag, as SGML (the language which HTML used to be derived from) tags cannot begin with a digit:
The element name immediately follows the tag open delimiter. An element name consist of a letter followed by up to 72 letters, digits, periods, or hyphens. Names are not case sensitive.
https://www.w3.org/MarkUp/html3/HTMLandSGML.html
Since the code is assigning the innerHTML
property of an Element
, the browser tries to parse the value as HTML and isn't treating <0>
as an HTML element, instead opting to treat it as a text value; whereas <div>
is a valid HTML element, so the browser treats it as such.
If you inspect the output in the console, you'll actually see an empty <div>
DOM node inside the paragraph p1
(and the string <0>
in p2
):
If you don't want the browser to parse the assigned value as HTML, use the safer, simpler textContent
property instead.