Recently, I've been learning JavaScript. I'm coming across a few JavaScript errors that say "__ is undefined" - What exactly does this mean, and why is this coming up? I'm looking more or less for an explanation on why this error is occurring and what can be done to fix it, or why it's generally occurring in the first place.
For example: Here are two functions (validate and onSearch) --- When I try to run "onSearch", I get the Ran SEARCH... trace in the console, however it disappears. Additionally, when I run it through JSHero (trying to debug), it tells me that "onSearch" is undefined, and I'm curious as to why.
I've go some experience developing with ActionScript, but I'm totally new to JavaScript. I'd really appreciate your input and explanation regarding what this actually means. Thanks you.
function validate(query){
console.log("Ran VALIDATE...");
// Trim whitespace from start and end of search query
while(query.charAt(0) === " "){
query = query.substring(1, query.length);
};
while(query.charAt(query.length-1) === ""){
query = query.substring(0, query.length-1);
};
console.log("Query length:",query.length);
console.log("Beginning conditional...");
// Check search length, must have 3 characters
if(query.length < 3){
console.log("Display alert...");
alert("Your search query is too small, try again.");
// (DO NOT FIX THE LINE DIRECTLY BELOW)
searchInput.focus();
}else{
console.log("Searching query...");
onSearch(query);
};
};
// Finds search matches
function onSearch(query){
//var search = function(query){
console.log("Ran SEARCH...");
// split the user's search query string into an array
var queryArray = query.join(" ");
// array to store matched results from database.js
var results = [];
// loop through each index of db array
for(var i=0, j=db.length; i<j; i++){
// each db[i] is a single video item, each title ends with a pipe "|"
// save a lowercase variable of the video title
var dbTitleEnd = db[i].indexOf('|');
var dbitem = db[i].tolowercase().substring(0, dbTitleEnd);
// loop through the user's search query words
// save a lowercase variable of the search keyword
for(var ii=0, jj=queryArray.length; ii<jj; ii++){
var qitem = queryArray[ii].tolowercase();
// is the keyword anywhere in the video title?
// If a match is found, push full db[i] into results array
var compare = dbitem.indexOf(qitem);
console.log("Compare:",compare);
if(compare != -1){
results.push(db[i]);
};
};
};
console.log("Hello");
results.sort();
// Check that matches were found, and run output functions
if(results.length === 0){
noMatch();
}else{
showMatches(results);
};
};
EDIT**
"db" is defined in an external file. It's just an array of URL's. It's still saying it's not defined as well, which is what I'm asking.
How do you define
1) A variable
2) A function
If you get a TypeError along the lines "Blah is undefined" or "cannot read property foo of undefined", it means that you have a variable or property that has the value undefined, which is the default value for a variable until you assign something to it.
This is as opposed to having a variable you haven't defined yet and trying to read its value, which will fire a ReferenceError instead.
For instance, consider the below:
var foo;
console.log(foo.bar); // "TypeError: Cannot read property 'bar' of undefined"
The foo variable exists, but its value is undefined, so trying to read a property from it causes an error.
Contrast that to:
console.log(missing); // "ReferenceError: missing is not defined"
Here, the symbol missing is not defined; the engine has no idea what you're talking about. This usually indicates a missing var statement.
Side note: JavaScript has a very surprising behavior if you assign to a variable you've never declared (in ES3 or in ES5 in "loose" mode): It creates a global variable. I call this The Horror of Implicit Globals. It means that if instead of console.log(missing); above, I did this:
missing = "foo";
...I'd be creating a new global variable, even if that code is within a function. Thankfully, in ES5, we can use "strict" mode, which makes this the ReferenceError it always should have been. :-)
It usually means that the 'thing' you're requesting does not exist(or atleast can't be found by the function requesting it). This can be a variable, object or a function.
In the case of the onSearch you're talking about is that the function can't be found, most likely. It could be that the file with the function in it is loaded after the file requests it(So onSearch is in b.js, the one requesting it is in a.js. a.js is in your <head> before b.js). Therefore it's not yet present, since javascript files load linear.
Your problem
The problem is not that onSearch is undefined, but it uses a variable db which is undefined.
Cases
(From now on I will assume qwertyuiopasddsghjdsvjkfhjkl is not declared)
You see undefined errors when:
You use variable you have not declared.
qwertyuiopasddsghjdsvjkfhjkl; // ReferenceError: qwertyuiopasddsghjdsvjkfhjkl is not defined
You use a property on a declared but undefined variable:
var a;
a.b; // TypeError: a is undefined
A variable is undefined when:
(Error) You have not declared it
// qwertyuiopasddsghjdsvjkfhjkl is undefined
qwertyuiopasddsghjdsvjkfhjkl; // ReferenceError: qwertyuiopasddsghjdsvjkfhjkl is not defined
(No error) You have declared it but it has no value
var a; //a is undefined
(No error) You assign a variable to void(0) (you can change 0 with everything) or and unmodified undefined
var a = undefined; //a is undefined
var a = void(0); //a is undefined
undefined = 'abc';
var a = undefined; //a is NOT undefined
How to check
If you don't know if a variable is undefined, you can use
typeof myVar === 'undefined'
It returns true if:
myVar is not declared
myVar is declared but is undefined
It returns false if myVar is declared and myVar is not undefined
myVar === void(0)
It returns true if myVar is declared and myVar is undefined
It returns false if myVar is declared and myVar is not undefined
It throws an error if myVar is not declared
myVar === undefined
It's the same as myVar === void(0) if undefined has not been modified.
!myVar, if(myVar)
It returns true if myVar is declared and
myVar is undefined
or
myVar is falsy (null, 0, false, '')
It returns false if myVar is declared and myVar is truthy
It throws an error if myVar is not declared
Related
I was just trying this JS code -
if(a){
console.log("a IS DEFINED")
} else {
console.log("a IS UNDEFINED")
}
and I am getting error -
ReferenceError: a is not defined
But when I add var a it prints a IS UNDEFINED
var a;
if(a){
console.log("a IS DEFINED")
} else {
console.log("a IS UNDEFINED")
}
// prints a IS UNDEFINED
Why it behaves differently where in both case a is undefined?
Your confusion is completely understandable: It's two different uses of the word "undefined."
There's a difference between an undefined identifier and the value, undefined.
When you do
if (a)
...you're trying to take the value of the identifier a. If you haven't defined that identifier at all, it's a ReferenceError. The JavaScript engine has no idea whatsoever what a is meant to be.
In contrast, this:
var a;
defines the identifier (as a variable) and gives it the initial value undefined. So then when you do
if (a)
...the JavaScript engine knows what you're talking about: It goes to the variable a and gets its value.
If for some reason you need to know if an identifier is defined and you don't want to catch the error, you're allowed to take the type of an undefined identifier:
if (typeof a === "undefined")
That works (without an error) even if a is completely undefined. However, it doesn't make any distinction between the two things (an undefined identifier, and a defined identifier with an undefined value).
Now, as if this weren't confusing enough, in "loose mode" JavaScript has a very strange behavior I call The Horror of Implicit Globals: If you assign to an undefined identifier (instead of trying to read its value), instead of giving a ReferenceError, it creates a new global variable. Thankfully, we now have ES5's "strict mode" which makes doing that the error it always should have been. :-)
I would recommend you to use:
if (typeof a === 'undefined') {
console.log('a IS UNDEFINED');
} else {
console.log('a IS DEFINED');
}
A variable has the type of undefined if it hasn't a value or if it wasn't declared before.
In short, when you don't declare a variable but using it inside your code, it gets a ReferenceError as the variable you are pointing to cannot be referred.But when you declare the variable but don't initialize it,then the value isn't defined.
Example :
First Case :
if(j){
//do something
}
didn't declare j, but referring to it.So it'll give an undefined error because of not getting j as a declared/known variable.
Second Case :
var j;
if(j){
//do something
}
Here j==null will be true, but if(j) will be equivalent to if(null) that is same as if(false), not because j is null. Rather because j is undefined.
I have below javascript function-
function ResponseVal()
{
this.value1;
this.value2;
}
var Response = new ResponseVal();
I tried and execute above code in chrome consolebar.I could not understand why newly created object "Response" does not show property value1 and value2. Can anyone help me to understand it what is happening and why properties are not displaying.
You should set the values to something. All you've done is try to read them in the constructor.
function ResponseVal()
{
this.value1 = "";
this.value2 = "";
}
var Response = new ResponseVal();
Declaring a property without setting it essentially does nothing. While it won't result in an error, some interpreters will throw a warning—as will strict mode, I believe.
JavaScript doesn't make this immediately obvious. For example, if you do this:
function Hello() {
this.value1;
}
var h = new Hello;
alert(h.value1);
The alert will read undefined. However, the property value1 was never actually accessed—it doesn't exist at all because you did not provide a value for it.
Rather than throwing an error, JavaScript returns undefined any time you try to access a property that doesn't exist. So you will get the same result if you write, say:
alert(h.property_that_doesnt_exist); //alerts 'undefined'
Iterating through the properties of h shows clearly that the property value1 does not exist:
for (var key in h) {
alert(key + ' = ' + h[key]);
}
This alerts nothing, because no properties will be found. However, if you set the property to the JS primitive undefined, the property WILL exist:
function Hello() {
this.value1 = undefined;
}
var h = new Hello;
for (var key in h) {
alert(key + ' = ' + h[key]); //alerts 'undefined'
}
You can run the above code here: http://jsfiddle.net/Acdmn/
But there's no good reason to set a property/variable to undefined. To create a property with an "empty" value, JavaScript programmers typically use null:
function Hello() {
this.value1 = null;
}
This makes it clear that the property was created intentionally, but you're not ready to give it a meaningful value yet.
Lastly, note that property definitions work differently from "normal" (private) variables explicitly set with var (even though these are also properties, in this case of the window object). If you write:
var foo;
alert(foo);
alert(some_undefined_variable_name);
The first alert will say undefined. The variable foo was created, does exist, and contains the primitive value undefined (even though you didn't set it explicitly). The second alert, however, will throw a reference error:
ReferenceError: some_undefined_variable_name is not defined
So JavaScript is unforgiving about using undefined variables, but it doesn't care if you try to use an undefined property.
They are still undefined. They only exist once defined.
You need to assign values to value1 and value2, 'null' at least.
I've looked a fair bit, so pardon me if this has already been answered.
I'm also curious as to what the actual term is called;
Is it "Ambiguous" for the type of arguments I am handling?
Anyways, the problem is that I want to be able to call a function like this:
prompt(_.define(variable, "DEFAULT VALUE"));
Basically, so that variables can have default values.
However, every time I try to do this, I get this error:
Timestamp: 6/11/2012 1:27:38 PM
Error: ReferenceError: thisvarisnotset is not defined
Source File: http://localhost/js/framework.js?theme=login
Line: 12
Here is the source code:
function _() {
return this;
};
(function(__) {
__.defined = function(vrb, def) {
return typeof vrb === "undefined" ? ((typeof def === "undefined") ? null : def) : vrb;
};
})(_());
prompt(_.defined(thisvarisnotset, "This should work?"), "Can you see this input?");
Not sure why it's doing this? I've called undefined variables as arguments in functions before and it worked just fine.
A completely undeclared variable can't be passed in JS; you can only pass declared variables or undeclared properties of other variables.
In other words:
var a; // you can do _.defined(a)
var a = undefined; // you can do _.defined(a)
a.b; // you can do _.defined(a.b), even though we never defined b
Basically, so that variables can have default values.
Why don't you just initialize the variable with a default value?
Or, just initialise the variable before calling defined.
var variable; // Note that this will not overwrite the variable if it is already set.
Or, even better.
var variable = variable || 'default';
Everything I've ever read indicates that in Javascript, the boolean value of an undefined variable is False. I've used code like this hundreds of times:
if (!elem) {
...
}
with the intent that if "elem" is undefined, the code in the block will execute. It usually works, but on occasion the browser will throw an error complaining about the undefined reference. This seems so basic, but I can't find the answer.
Is it that there's a difference between a variable that has not been defined and one that has been defined but which has a value of undefined? That seems completely unintuitive.
What is a ReferenceError?
As defined by ECMAScript 5, a ReferenceError indicates that an invalid reference has been detected. That doesn't say much by itself, so let's dig a little deeper.
Leaving aside strict mode, a ReferenceError occurs when the scripting engine is instructed to get the value of a reference that it cannot resolve the base value for:
A Reference is a resolved name binding. A Reference consists of three
components, the base value, the referenced name and the Boolean valued
strict reference flag. The base value is either undefined, an Object,
a Boolean, a String, a Number, or an environment record (10.2.1). A
base value of undefined indicates that the reference could not be
resolved to a binding. The referenced name is a String.
When we are referencing a property, the base value is the object whose property we are referencing. When we are referencing a variable, the base value is unique for each execution context and it's called an environment record. When we reference something that is neither a property of the base object value nor a variable of the base environment record value, a ReferenceError occurs.
Consider what happens when you type foo in the console when no such variable exists: you get a ReferenceError because the base value is not resolvable. However, if you do var foo; foo.bar then you get a TypeError instead of a ReferenceError -- a subtle perhaps but very significant difference. This is because the base value was successfully resolved; however, it was of type undefined, and undefined does not have a property bar.
Guarding against ReferenceError
From the above it follows that to catch a ReferenceError before it occurs you have to make sure that the base value is resolvable. So if you want to check if foo is resolvable, do
if(this.foo) //...
In the global context, this equals the window object so doing if (window.foo) is equivalent. In other execution contexts it does not make as much sense to use such a check because by definition it's an execution context your own code has created -- so you should be aware of which variables exist and which do not.
Checking for undefined works for variables that have no value associated but if the variable itself hasn't been declared you can run into these reference issues.
if (typeof elem === "undefined")
This is a far better check as doesn't run the risk of the reference issue as typeof isn't a method but a keyword within JavaScript.
Is it that there's a difference between a variable that has not been defined and one that has been defined but which has a value of undefined?
Yes. A undeclared variable will throw a ReferenceError when used in an expression, which is what you're seeing.
if (x) { // error, x is undeclared
}
Compared to;
var y; // alert(y === undefined); // true
if (y) { // false, but no error
}
That seems completely unintuitive.
Meh... what I find unintuitive:
if (y) // error, y is undeclared
var x = {};
if (x.someUndeclaredAttribute) // no error... someUndeclaredAttribute is implictly undefined.
Here's an example of Jon's explanation regarding environment records:
var bar = function bar() {
if (!b) { // will throw a reference error.
}
},
foo = function foo() {
var a = false;
if (a) {
var b = true;
}
if (!b) { // will not throw a reference error.
}
};
In strict mode, it is an error:
function a() {
"use strict";
if (!banana) alert("no banana"); // throws error
}
It's always really been better to make an explicit test for globals:
if (!window['banana']) alert("no banana");
It doesn't make sense to perform such a test for non-global variables. (That is, testing to see whether the variable is defined that way; it's fine to test to see whether a defined variable has a truthy value.)
edit I'll soften that to say that it rarely makes sense to thusly test for the existence of non-globals.
When a variable is declared and not initialized or it's used with declaration, its value is "undefined". The browser complains exactly when this undefined variable is referenced. Here "reference" means some piece of javascript code is trying to visit an attribute or method of it. For example, if "elem" is undefined, this will throw an exception:
elem.id = "BadElem";
or you use try/catch:
try { x } catch(err){}
This way you're not doing anything in case of an error but at least your script won't jump off the cliff...
undefined = variable exists but has no value in it
ReferenceError = variable does not exist
I'm doing some experimenting with this malicious JavaScript line: var undefined = true;
Every uninitialized variable in JavaScript has the value of undefined which is just a variable that holds the special value of 'undefined', so the following should execute the alert:
var undefined = true,
x;
if (x) {
alert('ok');
}
But it doesn't, and my question is why?
On further experimentation, I tried the following:
var undefined = true,
x = undefined;
if (x) {
alert('ok');
}
This time, the alert is executed.
So my question is...since in the first snippet x holds undefined (because it is not initialized), why didn't the alert execute? The strange thing is that when explicitly stating that x is undefined (x = undefined), the alert executed...
There is a difference between a variable named undefined and the value called undefined.
var undefined = true,
x;
In this example, the variable undefined is set to the value true, and x to the value (not the variable!) undefined.
var undefined = true,
x = undefined;
In this example, the variable undefined is set to the value true as well, and x is set to the value contained in the variable undefined (which is true).
So, while you can declare a variable named undefined, you cannot change the fact that non-initialized variables are set to the value undefined.
Just declaring a variable called "undefined" does not mean that you're overriding the built-in concept of what the native "undefined" value is.
Imagine if Java would let you use "null" as an identifier. Well, I guess Java doesn't have the same coercion as Javascript. Anyway the Javascript statement
if (x) alert("foo");
involves an implicit coercion of the value of "x" to boolean. The value isn't defined, so its coercion to "boolean" results in false.
Uninitialized variables get the special value undefined. When you assign a variable to another variable you're giving it a string that references a variable you've defined within the current scope. In this case you've defined a variable named undefined so the JavaScript engine will look first through the variables, see that you've named one undefined and then assign it that variable.