Why does this code throw ReferenceError: test is not defined? - javascript

var te‌st = 1
console.log(test)
Try running this simple code. It gives error: ReferenceError: test is not defined, despite the fact that I defined that variable. Why is this happening?

In the variable declaration, the variable name contains a zero-width non-joiner (ZWNJ) character (between e and s), which is invisible, because its width is equal to zero. However, ECMAScript specification allows this character as a part of variable name.
However, in the console.log() call, there is just test, without any special characters. Therefore, it throws Reference Error, because the variable name is te<ZWNJ>st, not test.
Fortunately, there's an easy way to check if a variable name contains such characters. You can paste your code into JS Bin or JS Fiddle — they denote these characters with a white dot on a red background. That's how it looks like in JS Fiddle:
I think there are also similar features in some IDEs.
Side note: this is an interesting way to prevent people from copy pasting the code snippets you use in answers into their own code. Consider the following code snippet:
// Warning: non-copy-pastable, it won't work if you copy it into your code.
function a‌dd(a, b) {
return a + b
}
console.log(a‌dd(2, 3))
There's a ZWNJ character in the function name and the function call, so it works here. However, if someone copied the function into their code and then manually typed console.log(add(3, 4)), it would throw ReferenceError: add is not defined.
Please don't take the above seriously, it's rather a joke than a practical use.
Related
What characters are valid for JavaScript variable names?
No visible cause for “Unexpected token ILLEGAL”

Related

visual studio code javaScript lib.dom.d.ts(17177, 5) error [duplicate]

My editor (VS Code) shows that my variable name is deprecated. The variable name is struck out from the 2nd line. Can you help?
let name = 'Mark';
name = 5;
console.log(name);
In a browser, the global name variable has special meaning. This has caused people a lot of confusion over the years as they tried to create their own global variable named name and then found it coerced into a string.
The checker you are using doesn't appear able to special case an assignment to name if it follows a declaration of let name.
You can see that the message goes away if you put the code inside a function.
Just to clarify, whenever something is striked out, its a warning that it basically used a lot and might be interfered with. Its just a warning for variables with basic names. You don't need to worry about it
In VS Code, find the variable name where it is showing deprecated name. Put your cursor and right click on it, then select 'Go to Definition'. It will open another file named as lib.dom.d.ts.
Just remove the line "declare const name: void;"
This will remove your variable name from the deprecated list.

Integer by itself in a javascript file

I found a typo in one of my javascript files where there was an integer just sitting on a line on its own with nothing else. The file never errored out because of it so I was wondering, how does javascript handle or evaluate a line with just an integer on it and nothing else 'behind the scenes'?
The following is a valid statement:
4;
Of course, it would make more sense to do something like var num = 4;, but what you're doing above is the same thing, you're just not saving it's return value to a variable.
You can even have completely empty statements. The following is a valid, empty statement:
;
So you could have a program that looks like this:
var num = 4;
4;
;
Each of those lines would be valid.
Well, "5" is a code, that returns 5. You can try it out by opening Chrome Dev Tools (Press F12), then open console and enter a number. It will return a number, so it is valid piece of code.
You can write any expression in a line, in fact, it is referenced an ExpressionStatement in the grammar. So the line 4; is a statement, which evaluates, but never sotres it's variable; You can even leave the semicolon in most cases because of Automatic Semicolon Insertion.
These statements get evaluated, but then the resulting value is ignored, meaning that single number or string literals will not have any side effect (like 1+2+3;). However, calling functions or accessing variables or fields can have side effects (like: 1+a()+b), a gets accessed and called, b gets accessed).
But there are special cases, like "use strict";, which old engines just skip over as it is just a StringLiteral inside an ExpressionStatement, but modern browsers notice this line, and switch to strict mode.

Does javascript use some sort of implicit "noop" call?

This is probably JS 101 but...
Can someone with a better understanding of JS engines explain to me why string literals, integers and so forth are 'ignored' by JS or treated as otherwise valid code?
JS Hint does give 'unexpected expression' reports however the code remains valid and runs.
I've created the following pen to, hopefully, explain what I mean here.
http://codepen.io/billythekid/pen/zyGbi/
var span = document.getElementsByTagName('SPAN')[0];
// let's show what I'm trying to say here by way of an expanded example.
function foo()
{
var bar = "something";
}
foo(); // does nothing useful, but returns nothing either - valid and understandable;
function baz()
{
return "nothing"; // a string
}
function zoo()
{
return 250; // an integer
}
var a = baz(); // the variable holds the return value. The function is evaluated and the return value is assigned to the variable.
span.innerHTML += a+"<br>";
baz(); // produces no error despite the function returning a value. Why doesn't the JS engine see this as the evaluated string "something" and try to run the string as a JS command?
span.innerHTML += "this code has run, so the JS didn't break above. Why wasn't the returned string parsed and invalid?<br>";
"something"; // the string literal
span.innerHTML += "this code has run, so the JS didn't break above. So why not? How is a string literal valid JS? Why no errors?<br>";
var b = zoo();
span.innerHTML += b+"<br>";
zoo();// produces no error despite the function returning a value. Why doesn't the JS engine see this as the evaluated integer 250 and try to run the string as a JS command?
span.innerHTML += "this code has run, so the JS didn't break above. So why not? How is an evaluated integer valid JS? Why no errors?<br>";
250; // the integer literal
span.innerHTML += "this code has run, so the JS didn't break above. So why not? How is an integer literal valid JS? Why no errors?<br>";
eval(250); // the integer literal
span.innerHTML += "this code has run, so the JS didn't break above. So why not? How is an evaluated integer literal valid JS? Why no errors?<br>";
eval("something"); // the string literal
span.innerHTML += "this code broke, it can't run a string that's not been defined as a function or whatever.<br>";
// and, had the previous code not broken...
non_func(); // doesn't exist!
span.innerHTML += "this code doesn't run! So it'll error out with a call to a function/variable that doesn't exist but not eval'd code that isn't JS, such as a string, or even the literals of these objects!<br>";
// It appears that anythign not explicitly wrapped in an eval function is ignored by JS rather than throwing any errors. Why is this?
Simply running a string literal such as "foo"; as a line in the console seems to return itself.
Is the JS internally wrapping simple cases like these in some sort of 'noop' method or internally garbage-collecting such things or does it simply see the code as "run" once it's gone past it and has nothing more to do (such as assign values to a variable, or some other thing?
I got to thinking about this when using a setInterval() call, if I assign it's return value (well, it's ID identifier) to a var for using in a clearInterval later it's valid but it's also valid when we ignore the returned ID. The ID isn't "parsed" as JS.
Using strict mode seems to have no effect on this behaviour either.
Hopefully I've not made this more confusing than it needs to be. :oD
One big culprit behind your confusion is the C programming language. In it, many things that you think are statements, such as assignments, are actually expressions.
//This is valid C and Javascript code
x = (y += 1);
//We all have been bitten by this one once haven't we?
while(x = y){
}
and in order to let these statements be used in lines of their own, there is a rule in the language grammar that lets an expression followed by a semicolon to count as a statement
stmt :=
<if_then_else> |
<while loop> |
... |
<expression> ';'
The rule for evaluating these single-expression statements is that the expression is evaluated for side-effects and its value gets ignored.
Javascript (and lots of other languages) adopted lots of things from the C syntax, including this particular treatment of expressions. Using a string as a statement does nothing with its value (unless the string is "use strict" - then its a useful hack that does something in new browsers but nothing in the old ones). Using a function call as a statement runs it for side effects and ignores its return value. Some more stingy languages, such as Haskell or Go will complain if you ignore return values but C and Javascript will just throw them away.
-- In Haskell you get a compiler warning for ignoring return values
do
functionThatReturnsNothing()
a <- functionThatReturnsAValue()
_ <- functionThatReturnsAValue() -- unless you ignore it explicitly
It appears that anythign not explicitly wrapped in an eval function is ignored by JS rather than throwing any errors.
Thank god its that way! It would be crazy error prone if things got implicitly eval-ed like that and strings should never be run as code unless you are explicit about it!

Error : missing new prefix when invoking a constructor

I am trying to create a function in node.js. The following is relevant code, it gives me error when i call function.
function ReplacePlaceholders() {
return 'success';
}
exports.sendMailMsg = function (templateName, receiverEmail, dataPlaceholders) {
ReplacePlaceholders();
}
In node.js, function names are camel cased, and should start with a lowercase character. Starting a function with an uppercase character tells JSHint to consider the function a constructor rather than a method.
This is actually an error being generated by JSHint, but the code will run correctly. The option in JSHint, newcap, which causes this error is actually depreciated, and disabling it is recommended.
The relevant info as to why this option is even in JSHint:
This option requires you to capitalize names of constructor functions. Capitalizing functions that are intended to be used with new operator is just a convention that helps programmers to visually distinguish constructor functions from other types of functions to help spot mistakes when using this.
Not doing so won't break your code in any browsers or environments but it will be a bit harder to figure out—by reading the code—if the function was supposed to be used with or without new. And this is important because when the function that was intended to be used with new is used without it, this will point to the global object instead of a new object.
The error message you mention is a JSHint error message, not a runtime error. There is a discussion of it here:
jshint expects the new 'prefix' for functions
JSHint expects functions that start with a capital letter to be object definitions. You can ignore the error, disable it in JSHint, or rename your function so that it starts with a lower-case letter.
I'm not sure why that might be, but that error suggests that doing new ReplacePlaceholders(); might work. Though, you may want to consider something like the following:
function ReplacePlaceholders(templateName, receiverEmail, dataPlaceholders) {
return 'success';
}
exports.sendMailMsg = ReplacePlaceholders;

No semicolon before [] is causing error in JavaScript

var a = [1, 2, 3, 4];
var b = [10, 20, 30, 40];
console.log([a, b].length)
[a, b].some(function(x) {
x.push(x.shift())
});
I was extremely surprised today when this code caused
[a,b].some(function(x){ x.push(x.shift()) });
^
TypeError: Cannot call method 'some' of undefined
Obviously the JavaScript 'auto semicolon insertion' is not working as expected here. But why?
I know you might recommend to use ; everywhere to avoid something like that, but the question is not about whether it is better to use ; or not. I would love to know what exactly happens here?
When I'm worried about semicolon insertion, I think about what the lines in question would look like without any whitespace between them. In your case, that would be:
console.log([a,b].length)[a,b].some(function(x){ etc });
Here you're telling the Javascript engine to call console.log with the length of [a,b], then to look at index [a,b] of the result of that call.
console.log returns a string, so your code will attempt to find property b of that string, which is undefined, and the call to undefined.some() fails.
It's interesting to note that str[a,b] will resolve to str[b] assuming str is a string. As Kamil points out, a,b is a valid Javascript expression, and the result of that expression is simply b.
In general, one could say that implicit semi-colon's can easily fail when defining an array on a new line, because an array defined on a new line is interpreted as a property access of the value of the expression on the previous line.
Javascript does only consider new lines to mark the end of a statement if not ending the statement after this new line would cause a parse error. See What are the rules for JavaScript's automatic semicolon insertion (ASI)? and EcmaScript 5 spec for the exact rules. (Thanks to Rob W and limelights)
What happens is the following:
The code get interpreted as
console.log([a,b].length)[a,b].some(function(x){ x.push(x.shift()) });
i.e. all as one statement.
Now parse the statement:
some is called on the value of console.log([a,b].length)[a,b]
the value of console.log([a,b].length)[a,b] is computed by taking the returned value of console.log([a,b].length) (undefined) and then trying to access the property with the name of the value of a,b.
a,b evaluates to the value of b (try it in your console). There's no property with the value of b of undefined, so the resulting value will be undefined as well.
There's no method some on undefined, hence the error.
JavaScript doesn't treat every line break as a semicolon. It usually treats line
breaks as semicolons only if it can’t parse the code without the semicolons. Basically, JavaScript treats a line break as a semicolon if the next non-space character cannot be interpreted as a continuation of the current statement. JavaScript - The Definitive Guide: 6th Ed. section 2.4
So, in your case, it is interpreting the line as something like
console.log([a,b].length)[a,b].some(function(x){ x.push(x.shift()) });
And that is the reason for error. JavaScript is trying to perform array-access on the results of console.log([a,b].length). Depending on the JavaScript engine and the return value of console.log, you might get different errors.
If it is the last statement of the function or flow, you can avoid ';' but it is recommended to put ';' at the end of the each statement to avoid such error.

Categories

Resources