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 elements). As a result, many programmers - especially newcommers to the language - tend to BoldlyGoWhereSomeoneHasGoneBefore with messy, bandwidth obese results. A standard way to include other scripts from a script - as well as a standard library - would do well toward promoting more code reuse and better JavaScriptCodingStyle. ---- '''No good way of controlling for/in access to properties''' In JavaScript, some properties are not iterated over by for/in loops. These properties are usually built into the language and return false for the object's propertyIsEnumerable() method. If the programmer overrides one of these properties, it automatically becomes enumerable. There is no way (to my knowledge) of preventing an object's property being iterated by a for/in loop. One way to overcome this issue is to never mix objects with properties-as-data and properties-as-methods. Sometimes the difference between the data and methods becomes blurred, and this pattern creates more harm than good. ---- '''typeOf null == "object"''' The typeOf operator tells you which built-in type a variable is. Possible values include: * number * string * boolean * function * undefined * object Primitives boxed as objects are interpreted as objects. Thus note that ''typeof new Number(8) == "object"'', while ''typeof Number(8) == "number"''. The problem stems from the fact that ''typeof null == "object"'' in JavaScript. This makes life a little harder when you absolutely need to know if a value is null. A workaround is to test for having a type of an object (although it really isn't an object), then for being null: function isNull(vv) { return typeof vv == "object" && vv == null; } This function should return true iff ''vv'' is null. It had to test that typeof returns "object" first, since an undefined value is also equal to null but returns a typeof "undefined". Just use vv === null. -- StragerNeds ---- '''Variables are global unless declared local.''' In this example: function f() { var aa = 10; bb = 20; } Variable ''aa'' is local and ''bb'' is global. That is, ''bb'' is first retrieved from the parent code block's scope. If it isn't found, the parent's parent's scope is searched. And so on... This process is called searching the scope-chain. If ''bb'' is first accessed from the top-level code of the script, it becomes a property of the global object. For example, in HTML web browsers: 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. ---- CategoryJavaScript