JavaScript and EcmaScript have their share of design flaws. Some of these continue for backwards compatibility with the early days of web scripting. Others are simply differences of opinion among developers. (shocking that it happens ;-) Here are some examples:
No Built-In Array Iterator
The properties of dictionaries/objects can be iterated using a for/in loop:
var dict = {
one: 1,
two: 2,
three: 3
};
for (var ii in dict) {
// Do Something
}
The order of the iteration is undefined by the standard, because the intent is to iterate over unordered structures like hashes.
This means that some algorithms - that are sensitive to their order of execuation inside the loop - may be impractical or behave differently in different implementations. In particular, iterating over an array can be the source of many bugs. For/in loops will iterates through both the indices and enumerable properties of the array, as the following example shows:
var aList = [2,3,4,5,6,7,8,7,6];
aList.bad = "bad";
aList.stillbad = "more bad";
aList.map = function(each) {
return "see, it iterates properties, still not reliable to use for in";
};
for(var each in aList) alert(aList[each]);
A solution is to write a HigherOrderFunction to iterate over an array and use closure to pass a function containing the code to be iterated:
function forEach(anArray, aProcedure){
for(var index=0; index
aProcedure(anArray[index]);
};
var scopedVar = 12345;
var aList = [1, 2, 3, 4, 5];
forEach(aList, function(anItem){
doStuff(anItem, scopedVar);
});
Some people believe that function like the above belong in the core library of the language (even though ECMAScript doesn't technically have library support). Programmers shouldn't have to be ReinventingTheWheel for simple, general-purpose algorithms. Subtle incompatibilities and bugs can crop up, and less code reuse could reduce efficency.
Others believe that functions like this should be written into external libraries. Languages like Lisp and Smalltalk make the case pretty well that it's very flexible and extensible to leave some control structures outside of the language. It doesn't force you into limited constructs offered by the language.
If JavaScript supported RealMacros - such as a LispMacro - then new control structures could be added to the language. For example, the above solution could be rewritten as:
var scopedVar = 12345;
var aList = [1, 2, 3, 4, 5];
forEach (var anItem in aList){
doStuff(anItem, scopedVar);
};
Note that the macro was not shown, because JavaScript doesn't have macro support!
MozillaFirefox 1.5 implements JavaScript 1.6. The Array object has these new methods: every(), some(), forEach(), filter(), and map(). See BlocksInJavaScript and http://developer.mozilla.org/en/docs/New_in_JavaScript_1.6 .
{It needs to have a fricken built-in table engine. --top}
[What's a "fricken table engine"?]
No Libraries
JavaScript can be used to build programs of both small size and also great heft. However, ECMAScript doesn't really define anything like libraries to help wth code reuse. The closest things are scripts running in the same environment and the built-in objects/methods. You have to outside the spec and use multiple source files glued together by the environment (e.g. HTML
If one forgets to declare all local variable before using them, subtle gremlins can pop up in a program. For example, one function could modify another's variables. These types of bugs are hard to find and sometimes fall though even extensive testing.
Strict adherence to a good JavaScriptCodingStandard could help prevent some bugs; however as programmers are only human, mistakes are bound to be made. The default should be local, and you should have to work to make a variable global, e.g.
function f() {
aa = 10; // local
var cc = 20; // local
var.parent bb = 20; // parent scope
var.parent[1] dd = 42; // parent's parent scope
var.self ee = 50; // global scope
}
Note that the above is not legal JavaScript. It is just a possible alternative that the creators of JavaScript could have chosen instead (but didn't).
Octal integer literals
and... non-octal integer literals... If a number contains the digits 0-7 and has a leading 0, it is interpreted in base eight and not base ten:
var arr_flight = 0708; // this is decimal
var dep_flight = 0707; // this is octal
ARGH
Weirdness initializing arrays
An array constructor with zero arguments creates an empty array. An array constructor with n arguments where n>=2 creates an array with n elements; those being the arguments to the constructor. Ex:
var ary = new Array(1,2,3,4,5); // ary = [1, 2, 3, 4, 5]
However, if an array constructor with one argument is used, that argument is not interpreted as the single (initial) element of the array; it's the size of the array (the array then gets that many null elements). Ex:
var ary = new Array(5); // contains 5 elements (each undefined)
While an initial-size constructor is often useful, the "new Array(1,2,3,4,5)" form is aberrant. But now it's a legacy issue and so far hasn't been removed.
Offsite Issues
DouglasCrockford has some good articles in praise of and criticizing JavaScript at http://www.crockford.com.
See also: JavaScript, JavaScriptRocks, JavaScriptSucks.