So I have been working with javascript for a website I am designing, shocker I know, I was trying to find a way to test if a variable did not exist or wasn't defined. After getting through this I think being undefined and not existing are two different things. Also I think its highly unlikely I found a bug but maybe someone with a better understanding of Javascript can explain to me why the following code works the way it does.
<script type="text/javascript">
var t1="";
var t2;
if (t1==undefined) {document.write("t1 is undefined");}
if (t2==undefined) {document.write("t2 is undefined");}
</script>
The above code returns "t2 is undefined".
<script type="text/javascript">
var t1="";
if (t1==undefined) {document.write("t1 is undefined");}
if (t2==undefined) {document.write("t2 is undefined");}
</script>
This second code crashes I believe. So in the first code t2 exists but is not defined? and in the second code it needs to exist before it can be undefined? I just figured that if I did not write "var t2;" then tested for it, it would be undefined. Hopefully I have explained this question enough.
It's not a bug. In fact, the typeof operator is the only place where you can use an undeclared variable without getting an error.
See my answer Internet Explorer: "console is not defined" Error for a detailed explanation
edit:
This is how it's defined in the specs:
The production UnaryExpression : typeof UnaryExpression is evaluated as follows:
1. Let val be the result of evaluating UnaryExpression.
2. If Type(val) is Reference, then
a. If IsUnresolvableReference(val) is true, return "undefined".
...
Everywhere else, IsUnresolvableReference==true results in an error.
Well in your case if you have:
var t1 = "";
You will declare an empty string so it is normal to be "defined";
Whilst by doing:
var t2;
You are not defining it as any type of javascript object
It seems that there's a confusing naming convention here;
We can say in the first case, you define variable t2 itself but it does not have a value defined. You can think the "undefined" property as the "value-undefined" to be more precise.
In the second case, you have t2 variable itself is NOT defined, thus you will get an error when you try to use it in code: "variable undefined", this error is because of a different reason but it is named similarly, making the situation a little confusing. Think this error as "variable-undefined" to be more precise.
I think you can just use the property "null" instead of the "undefined" in the first case to be clear.
var t1="";
var t2;
if (t1==null) {document.write("t1 is null");}
if (t2==null) {document.write("t2 is null");}
and;
var t1="";
if (t1==null) {document.write("t1 is null");}
if (t2==null) {document.write("t2 is null");} // this line gives error because t2 variable is undefined
Related
I'm currently playing around with "const" variable in javascript and here is my code
My question is, why is "const x" undefined when used with "console.log", but it is defined when used on its own?
p.s. -- I understand that both global "const, let" do not become the property of "window" object, unlike global "var". But I am unsure as to whether this played any role in the code above.
You're seeing undefined because console.log() function actually returns you that.
Notice how x is still 123 when you query just x?
The assignment operation for const x = 123; is undefined because it returns you undef as well.
What browser/version are you using? Trying it in both FF65 and Chromium71, console.log( x ); indeed gives me 123 ...
I'm working on some existing code that looks something like this:
return this.getMyObject() && this.getMyObject().myArray[0];
As far as I can tell it is checking that the object returned by getMyObject() exists before returning the first item in it's myArray property. How does this work and is it good form?
Update: The reason for my question came from the confusion over how the && operator can be used to return a property value and not a boolean result. After further thought, to make it more readable I refactored the line to:
return this.getMyObject() ? this.getMyObject().myArray[0] : undefined;
Obviously I am assuming here that the myArray property will exist.
That code works because of type coercion. Some people will tell you its good and some people will say always truly check something using typeof
if (typeof someVariable === 'undefined')
Even in examples below the above check isn't enough. I don't know what is better but that code as far as I am concerned isn't how I write it myself but it is accepted with a lot of javascript developers. There are times that code in the correct conditions can still pass the first check and yet throw an error accessing the property. Depends how controlled your situation is that determines, to me, if you should or shouldn't allow it.
Example of passing first check and failing:
var myObject = 1;
var test = myObject && myObject.myArray[0];
Or as #JamesThorpe pointed out in comment above:
var myObject = {};
var test = myObject && myObject.myArray[0];
Also people familiar with some coding languages but not JS might look at that code and not understand what it means where checking with an if and then returning the value might be a bit more readable to others, which is also a plus I think.
It's correct form. If there is no object returned by this.getMyObject() then function will return false in another case second part of condition will be executed and returned as a result of function. It's good practice to check if object exists before calling any method on it, because an error could occur if not to do so.
But you should check an existence of an object only if you are not sure whether it exists.
It seems a solution for error message
TypeError: Cannot read property XXX of undefined
when using something like
if (item.property) {....}
is no longer valid. In fact, it seems even getting that error message is no longer possible because now you get
ReferenceError: item is not defined
I came across this because quite some time ago I had posted an accepted and 13 times upvoted answer to just such a question. I was not the only one giving the code that I gave as an answer, here is another one - same code, for the same type of problem. But those solutions now result in an error immediately!
I DID test my code, and if it had not worked it would hardly have been upvoted and accepted, same for the other Q/A I link to.
What is going on? I can't seem to provoke that error message (Cannot read property XXX of undefined) any more either, I tried by accessing a property of an undefined or a null variable. Have I gone mad, or has something else changed?
No, this hasn't changed (there's something similar that's changed, but not this; more below). Here's the difference: If item isn't declared, then you'll get the error about item. If item is declared but has the value undefined, you'll get the error about reading a property of undefined. This has always been the case.
You mentioned Firefox. Firefox's error messages for these two different conditions are confusingly similar. If the variable is undeclared, it says:
ReferenceError: item is not defined
But if the variable is declared and has the value undefined, it says:
TypeError: item is undefined
Note the difference, but the extreme similarity. I would say Firefox's error messages are poor in this regard. Chrome's are more clearly distinct:
ReferenceError: item is not defined
TypeError: Cannot read property 'property' of undefined
But that's just the error message. The underyling issue, trying to read the value of an undeclared symbol, has always been an error.
Re the two answers you linked to: I'm sorry, but they were always wrong for the undeclared case (and right for the undefined case), this is just something that people don't understand well. If item may be completely undeclared, you can't use that idiom. You can use typeof, though:
if (typeof item !== "undefined" && item.property)
typeof is fine with undeclared symbols, but reading the value of an undeclared symbol is an error, as has been for as long as we've had JavaScript.
Here's a question from 2011 about this. The accepted answer with a score of 1,016 talks about typeof.
Here are examples of both cases:
Undeclared:
// Note that `item` isn't declared anywhere at all
try {
if (item.property) {
snippet.log("true");
}
}
catch (e) {
snippet.log((e.name || "Exception") + ": " + (e.message || String(e)));
}
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
Declared but has the value undefined:
var item;
try {
if (item.property) {
snippet.log("true");
}
}
catch (e) {
snippet.log((e.name || "Exception") + ": " + (e.message || String(e)));
}
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
The similar thing that's changed is how assigning to something that isn't declared at all is handled:
item = "foo";
In loose mode, that's an implicit global variable, even if the assignment is inside a function. In ES5's strict mode, though, it's an error.
But that doesn't relate to reading the value of an undeclared variable, which was always an error, just writing to it.
From the OP:
when using something like
if (item.property) {....}
is no longer valid. In fact, it seems even getting that error message is no longer possible because now you get
That is incorrect.
In both linked questions, the OPs mention item being undefined, which means they are declared, which means the answers, if (item && item.property), will work exactly as expected.
Nothing has changed in this regard, so to answer your question:
why things that worked don't work any more. I link to TWO answers that were accepted and highly upvoted that don't work (any more)!
Those answers work just fine. Unless you change the parameters of the question, which is what you're doing.
(You're assuming item is undeclared instead of undefined)
There's a difference between a typeof being "undefined" and the actual variable being undefined:
This gives correct answer:
<script type="text/javascript">
var numbers=[67,56,45,34,78,54,67,90,43,56,78,90,23,45,67,89,54,1];
var sita=0;
for(i=0;i<numbers.length;i++){
if(numbers[i]>sita){
var sita=numbers[i];
document.write(sita+" ");
}
}
</script>
This is not working:
<script type="text/javascript">
var numbers=[67,56,45,34,78,54,67,90,43,56,78,90,23,45,67,89,54,1];
for(i=0;i<numbers.length;i++){
if(numbers[i]>sita){
var sita=numbers[i];
document.write(sita+" ");
}
}
</script>
why?
as others have mentioned sita is undefined in the second example.
a larger or smaller comparison against undefined - in that specific situation of yours - always yields false, no matter against what you compare.
so, your expression translates to
if (false)
EDIT:
I completely missed line 5 of the second example because so many people wrote that the variable sita was undefined when in fact just it's value is undefined. So enabling strict mode won't do much good here. Anyways, just for reference, my original post:
To avoid mistakes like that you should always (or if not always then
at least while debugging) use the strict mode (available since
ECMAScript 5).
"use strict";
link:
What does "use strict" do in JavaScript, and what is the reasoning behind it?
Say you're the interpreter. And you've reached the line if(numbers[i]>sita){ what would you think, what value has the sita variable?
You have to define variabls before using them (like in the first example). Otherwise interpreter won't know what means that word.
In your first code example sita is defined just before the for and within your if statement. I would assume that your second definition var sita = numbers[i] should look like sita = numbers[i].
In your second code example sita is not defined before use - only within your if. So sita is undefined and your if condition won't check out and nothing will be printed.
I just got the following error in a piece of javascript (in Firefox 3.5, with Firebug running)
cannot access optimized closure
I know, superficially, what caused the error. I had a line
options.length()
instead of
options.length
Fixing this bug, made the message go away. But I'm curious. What does this mean? What is an optimized closure? Is optimizing an enclosure something that the javascript interpretter does automatically? What does it do?
I had this issue too when Firebug is running.
It seems to happen sometimes, when an exception is raised (for whatever reason) and when there's a recursive function call somewhere in the call stack. The exception gets re-raised as the mysterious "InternalError: cannot access optimized closure"
Changing the way I define the recursive function, seems to make this issue go away. eg changing from
function foo(bar) {... foo(recursively); ...}
to
var foo = function(bar) {... foo(recursively); ...}
Hope that helps.
It is a bug in Firefox happening with Firebug open:
https://bugzilla.mozilla.org/show_bug.cgi?id=505001
[An earlier answer mentioned this was due to this other bug, which I think is incorrect as that other problem was not related to Firebug.]
Seems like a Firefox bug:
https://bugzilla.mozilla.org/show_bug.cgi?id=496790
A closure is a function with context. If you dynamically create a new function, then you create a closure.
function makeAdder(int num) {
return function(int num2) { return num + num2; }
}
adder = makeAdder(5);
adder(7) // returns (5+7) = 12
adder(2) // returns (5+2) = 7
Here, the closure is the inner function, as returned by makeAdder, along with the '5' that was passed.
The javascript engine might choose to optimize away the function shown above, to make things run faster, never generating or running that code, so it can't be debugged or referenced. Optimizers are supposed to be very careful to ensure there's no impact, so I'd guess this one made a mistake.
http://ludex-marketing.com/blog/2009/12/google-analytics-javascript-error-cannot-access-optimized-closure-in-ga-js/
This can also be caused by a simple race condition. I was just refactoring a 'startup' object that does a few things before the document is ready. As soon as I tried to access a second object defined immediately below the startup object I received this error.
I was under the impression that script execution waited until all of the code was compiled. Clearly that's not the case. Waiting for document ready to call methods on the second object fixed the problem. Also, using this nice 'dump()' function confirms that the second object is only partially defined when the error occurs: http://www.openjs.com/scripts/others/dump_function_php_print_r.php
I encountered the same error today. In my case this occurred because I was referencing an object's attribute or function that did not exist or was not available. I'm guessing that since the object was available via a closure that was optimized, firebug could not access metadata on that object and thus the cryptic error message.
This also happened to me today. Firebug error'd at line 2 of this function:
function IsValidDate(objName) {
re = new RegExp('^( +|today|pdate|- *\\d+ *(day(s|)|week(s|))+ *$', 'i');
if (re.test(objName.value)) return 2;
return (chkdate(objName));
}
When I added "var " before the declaration of "re" in line 1, the error went away.
There is an exception being raised somewhere else in your code within the function that has this error. It could be as simple trying to access a variable that doesn't exist.
I think we need to get a Firebug dev in here to answer why it doesn't give a more specific error as to where in the closure that raised the exception to prompt the error.
You pasted options.length(), but it is not what prompted the error. What caused the error is the fact that your bug was inside a closure.
function(){
array.length()
}
that gives the error