9 ms·
From a synopsis of a Crockford presentation (here http://www.catonmat.net/blog/javascript-the-good-parts/ http://www.catonmat.net/blog/javascript-the-good-parts
by jsvaughan 15y ago
From a synopsis of a Crockford presentation (here http://www.catonmat.net/blog/javascript-the-good-parts/ http://www.catonmat.net/blog/javascript-the-good-parts/) here are some js bad parts:
* Global variables.
Global variables make it harder to run independent subprograms in the same program. If the subprograms happen to have global variables that share the same names, then they will interfere with each other and likely fail, usually in difficult to diagnose ways.
* Newlines get converted into semicolons. JavaScript has a mechanism that tries to correct faulty programs by automatically inserting semicolons. It sometimes inserts semicolons in places where they are not welcome.
* Operator typeof is not very helpful. For example, "typeof null" is "object", "typeof [1,2,3]" is also "object".
* Operator + adds numbers and concatenates. The + operator can add or concatenate. Which one it does depends on the types of the parameters. If either operand is an empty string, it produces the other operand converted to a string. If both operands are numbers, it produces the sum. Otherwise, it converts both operands to strings and concatenates them. This complicated behavior is a common source of bugs. If you intend + to add, make sure that both operands are numbers.
* Operators == and != do type coercion. Use of the === and !== operators is always preferred.
* Too many falsy values. 0, Nan, '' (empty string), false, null, undefined are all false.
* for ... in operator mixes inherited functions with the desired data members (it does deep reflection).
- deleted 15y ago[deleted]
- ajuc 15y agoIMHO the worst problem with JS is too losely defined standard - typeof on array or on function on some implementations return Object, on some other something different, you often have to check for type of argument (when coding function that would be overloaded in languages that support this concept), and properly doing this is pain (checking is something is array is often done by checking if it has "length" property!). Still, JS is perfect example of how important closures are for programming language - they make very bad language acceptable.
- masklinn 15y ago> typeof on array or on function on some implementations return Object, on some other something different, you often have to check for type of argument You should not be using `typeof` on object types (and this includes functions) anyway. Use `instanceof`. > and properly doing this is pain (checking is something is array is often done by checking if it has "length" property!). This really checks if something is array-like (for instance the jQuery object would pass this "test", even though it's not an array. Likewise for `arguments` or a NodeList)
- ajuc 15y agoMaybe it's me not understanding dynamic typing etc, but it makes me afraid someon will use my code with object like that: var rope = { color: "red", length: 10 };
- masklinn 15y agoThere's nothing useful you can do against that kind of stuff, so I'd recommend you just document your API correctly and if people want to be stupid, them's the break. I mean nothing stops a java developer from implementing a List throwing some kind of NotImplementedException everywhere (in fact, using `java.util.Collections.unmodifiableList` would be sufficient as that's exactly what it does: throw UnsupportedOperationException on every access to a mutation method, so it's going to blow up any time it's passed to an API which wants to modify the list it's given)
- masklinn 15y ago> Too many falsy values. 0, Nan, '' (empty string), false, null, undefined are all false. I disagree with that, actually. I like that many Python objects can be used in a boolean context and behave sensibly, and that this behavior is accessible to user-defined-types. On this point, Javascript annoys me because on some things it works as Python (empty string) whereas in others it does not (empty array). > for ... in operator mixes inherited functions with the desired data members (it does deep reflection). It does not do any reflection, really. It just iterates on all enumerable properties of the object, inherited or not.
- benatkin 15y agoIt's nice how Python has "is False". In JavaScript it's "=== false". The python version reads a lot better IMHO.
- steve-howard 15y agoIt's more idiomatic in python to just test for truthiness (i.e. "not x" rather than "x is False"). There aren't a lot of cases where you'd want False to be false but not None, 0, or an empty container.
- masklinn 15y agoIt is quite common for `None` though.
- benatkin 15y agoTrue. If I'm expecting a bool and just writing is True to program defensively, what I should really be doing is assert(type(x) is bool) if I want to make sure I was given a boolean value or x = bool(x) if I want to make sure I'm outputting bool.
- T-R 15y agoThe worst part about these issues is that they aren't consistent, and fail completely silently. Global variables cause heisenbugs - you'll only notice when there's a collision, such as after compressing your script. The ==/!= operators and falsy values just put you on the wrong side of an if-statement. The for...in operator sometimes just loops a few extra times. The coercion and overloaded + operator will just sometimes give you a wrong number if you forget to caste an input: "25"+5 = 255 ("25"+5)/5 = 51
- masklinn 15y ago> The worst part about these issues is that they aren't consistent, and fail completely silently. Global variables cause heisenbugs - you'll only notice when there's a collision Firefox has had the ability to warn about implicit globals for quite some time now, and strict mode will error out when encountering an implicit global being created.
- reichstein 15y agoActually the problem with automatic semicolon insertion (ASI) is the opposite: It sometimes doesn't insert one where you expect it. ASI only inserts a semicolon when not inserting it would give a syntax error. It's the cases where a newline was really intended to end a statement, but doesn't, the bites you. Example ()creating a generator: var gen = null (function() { var ctr = 0; gen = function() { return ctr++; }; })(); Seems simple, but actually tries to call null as a function. Also, the + operator doesn't treat all non-numbers as strings. It tries to treat all non-strings as numbers, if possible. Only if that fails does it try them as strings. If either argument is then a string, it does concatenation.
- jashkenas 15y agoNice list. One of the things that CoffeeScript manages to do, with greater or lesser success, is to avoid many of these "bad parts": * Global variables can no longer be created by accident ... you must explicitly `window.global = ...` them. * Semicolons are gone, along with the headaches of automatic semicolon insertion. * I'm afraid that not much can be done about `typeof` without a more invasive replacement, unfortunately. * The + operator continues to work the same way. * CoffeeScript does not have `==` or `!=`, only `===` and `!==` for strict equality comparisons. In the one location where `==` can be helpful, checking for either null or undefined, you may use the existential operator. * When dealing with too many falsy values, there's an existential operator, which allows you to ask the question: Does this value exist? (Is this value not null or undefined?) name = "" if name? # Exists, so this will run. * There's a shortcut to only list the "own properties" when iterating over the keys and values of an arbitrary objects, without including members from the prototype chain: for own key, value of object alert key + ": " + value
- boucher 15y agoAmusingly (to me at least) the only thing Objective-J really addresses from that list is 'typeof', which we have a much better replacement for :).
- jashkenas 15y agoNice! Got a link to the implementation, or more info? The only reference I found to it is this thread: http://groups.google.com/group/objectivej/browse_thread/thread/f7489e3d71ee95f http://groups.google.com/group/objectivej/browse_thread/thre...
- boucher 15y agoYou're not going to like it :) Rather than use typeof, CPObject has a runtime feature for asking about its class (https://github.com/280north/cappuccino/blob/master/Foundation/CPObject.j#L179 https://github.com/280north/cappuccino/blob/master/Foundatio...). Because we also do "toll-free bridging", you can ask if strings are CPStrings, numbers are CPNumbers, and arrays are CPArrays (though we don't toll free bridge null to CPNull, which we probably should).
- podperson 15y agoI agree with most of Crockford's recommendations (and use jslint) but it's impossible to create a controlled experiment in which JavaScript was created without globals (or globals requiring declaration and locals being implicit) and inferred end-of-statement and find out if it would have been as popular. Globals make total sense to newbies, and avoiding them is not hard if you're not a newbie. (HyperTalk, if I recall correctly, had local variables by default and global variables explicitly, and was -- I think -- even more newbie friendly than JavaScript, so it's possible that JavaScript might have thrived.) It's not like coding in ActionScript is noticeably more pleasant than coding in JavaScript despite being controlled by a single vendor. And the dedicated ActionScript editor in Flash is far more annoying than a simple text editor. Anyway, "abominable" is a ridiculous word for a language that has so many broadly consistent implementations, is so approachable, and yet supports so many modern programming concepts with a compact and approachable syntax.
- masklinn 15y ago> (HyperTalk, if I recall correctly, had local variables by default and global variables explicitly, and was -- I think -- even more newbie friendly than JavaScript, so it's possible that JavaScript might have thrived.) That's what Python does, it has its own severe failings (especially when the language is lexically scoped). I like dynamically typed languages, but I've come to the conclusion that scope inference is terrible, and variable scoping should always be explicit (and probably statically checked as well), trying to infer variable scope will fail silently and badly.
- podperson 15y agoThe problem with making scope always explicit is that you then need to explain scope to newbies. Sure, it's worth explaining, but you just lost half your audience. Based on the success of BASIC (and indeed many, many early programming languages), global variables are easy to understand, local variables are less easy to understand. It's all very well to complain about JavaScript's lack of Important Language Feature X, but it's an easy language to learn and use for simple things and yet it's also pretty damn good for complex things (especially in combination with jslint). Along with many other Language snobs, I used to despise JavaScript, but it's the inconsistent DOM implementation that sucks -- IE's in particular -- along with some annoyances you can work around (like truthiness) that are the real issue; once you code with JavaScript and jQuery the DOM goes away and you're left with a very nice coding environment. Compare that to ActionScript 3 and the byzantine Flash/Flex (and constantly changing) class library and then decide which one deserves the adjective "abominable". And bear in mind AS3 completely broke compatibility with AS2 without actually becoming better organized.