What do you think this code will print out?
function validateURL(url) {
if (url.includes("://")) {
const url = new URL(url);
return url.protocol === "https:";
} else {
return "dunno";
}
}
console.log(validateURL("http://www.peterbe.com"));
I'll give you a clue that isn't helpful,
▶ eslint --version
v7.19.0
▶ eslint code.js
▶ echo $?
0
OK, the answer is that it crashes:
▶ node code.js /Users/peterbe/dev/JAVASCRIPT/catching_consts/code.js:3 const url = new URL(url); ^ ReferenceError: Cannot access 'url' before initialization at validateURL (/Users/peterbe/dev/JAVASCRIPT/catching_consts/code.js:3:25) at Object.<anonymous> (/Users/peterbe/dev/JAVASCRIPT/catching_consts/code.js:9:13) ... ▶ node --version v15.2.1
It's an honest and easy mistake to make. If the code was this:
function validateURL(url) {
const url = new URL(url);
return url.protocol === "https:";
}
// console.log(validateURL("http://www.peterbe.com"));
you'd get this error:
▶ node code2.js /Users/peterbe/dev/JAVASCRIPT/catching_consts/code2.js:2 const url = new URL(url); ^ SyntaxError: Identifier 'url' has already been declared
which means node
refuses to even start it. But it can't with the original code because of the blocking scope that only happens in runtime.
Easiest solution
function validateURL(url) {
if (url.includes("://")) {
- const url = new URL(url);
+ const parsedURL = new URL(url);
- return url.protocol === "https:";
+ return parsedURL.protocol === "https:";
} else {
return "dunno";
}
}
console.log(validateURL("http://www.peterbe.com"));
Best solution
Switch to TypeScript.
▶ cat code.ts function validateURL(url: string) { if (url.includes('://')) { const url = new URL(url); return url.protocol === 'https:'; } else { return "dunno"; } } console.log(validateURL('http://www.peterbe.com')); ▶ tsc --noEmit --lib es6,dom code.ts code.ts:3:25 - error TS2448: Block-scoped variable 'url' used before its declaration. 3 const url = new URL(url); ~~~ code.ts:3:11 3 const url = new URL(url); ~~~ 'url' is declared here. Found 1 error.
Comments