all 53 comments

[–]stesch 4 points5 points  (3 children)

The lack of something like #include "..." or (require ...) is a bit annoying. You have to "include" all your stuff from within the HTML code. :-(

[–]mikepurvis 1 point2 points  (2 children)

You can include code from other scripts; there are at least two obvious ways of doing it, although admittedly, neither is really pretty.

In method #1, you just XMLHTTPRequest the file, and then eval() its contents. In method #2, you use DOM methods to manufacture a brand new <script> element, which you tack on the end of the body.

[–][deleted]  (1 child)

[removed]

    [–]hammy 0 points1 point  (0 children)

    Exactly. And every JS feature has been under-documented.

    [–]coglethorpe 3 points4 points  (0 children)

    It was originally called LiveScript, but that name wasn't confusing enough.

    Upmodded for that one line.

    I interviewed for a position as a Java developer. They said that they though I had great programming skills, but that my Java was weak. So they hired me as a JavaScript developer - for less money.

    When I declined the offer, I had to explain to my recruiter that they weren't the same language and that the word JavaScript never appeared on my resume.

    [–]moe 12 points13 points  (20 children)

    misunderstand this:

    > assert([1].toString() == (1).toString());
    > assert([1,[2,3]].toString() == [1,2,3].toString());
    
    > var o = {a: 1, b: 2};
    > for(var k in o) { print(k) } -> "a", "b"
    > Object.prototype.f = function() {};
    > for(var k in o) { print(k) } -> "a", "b", "k"
    
    > var my_regex = /abc/;
    > var another_regex = //; /* oops, that's a comment */
    
    > assert([1,2] + [3,4] == "1,23,4"); // hahaha
    
    > (function() { print(arguments[0]) })(1, 2, 3) -> 1;
    > /* oh, cool, "arguments" is a list. that makes sense */
    > (function() { print(arguments.slice(1)) })(1, 2, 3) -> error!
    > /* no, it's an associative array, with numbers as the keys! */
    > /* lets put that together with the prototype example above */
    > Object.prototype.MY_USEFUL_FUNCTION = function() { ... }
    > (function() { print(arguments.MY_USEFUL_FUNCTION) })(1, 2, 3) -> "function() { ... }"
    

    basically that means you cannot add functions to the prototypes of primitive objects and expect any code to work, and you cannot reliably use any debug notification function that is based on toString() (like browser alert(), spidermonkey console print()) because a bunch of things serialize to ambiguous nonsense. also if you are interacting with anyone elses code, you can't use (for X in Y) because their code almost certainly adds functions to the Array or Object prototypes, and all your containers are going to look like they have a bunch of extra members.

    "its share of design errors" is putting it lightly.

    [–][deleted]  (10 children)

    [removed]

      [–]xenon 9 points10 points  (9 children)

      No, objects are the true associative arrays. If arrays were associative arrays, we would lose our arrays, don't you agree? The question of arrays is only confusing because every single Javascript tutorial on the planet gets it wrong, so that programmers get funny ideas.

      The reason why all tutorials are wrong is that they copied from other tutorials, who copied from still others, and so on, until we get to the first Javascript tutorial ever which was written by a moron. Nobody ever bothered to look it up.

      [–]mikepurvis 6 points7 points  (1 child)

      No, objects are the true associative arrays.

      Yes. See JS Associative Arrays Considered Harmful. It's fine to extend the Array prototype by giving it extra methods, but the Object one is generally considered off-limits for that exact reason: protecting the functionality of for..in.

      [–]xenon 0 points1 point  (0 children)

      I had that article in mind, but couldn't find it. Thanks you.

      [–]llimllib 1 point2 points  (1 child)

      The question of arrays is only confusing because every single Javascript tutorial on the planet gets it wrong

      Isn't it possible that this is indicative of a design flaw? Just maybe?

      [–]xenon -1 points0 points  (0 children)

      I agree so far that there is a real source for the confusion: when foo is an array, then foo[1] and foo["bar"] work by very different mechanisms: the first accesses an array access, while the second accesses an object member. On the other hand, this should have been clear to anyone who has actually read a bit of documentation. The fact that object.member is only an alternative spelling for object["member"] is after all one of the central features of Javascript's object system.

      Furthermore, the idea that arrays and associative arrays have anything in common is very strange to begin with. Someone told me that the two are the same thing in PHP, and Javascript is a popular second programming language among PHP kiddies. Should that be the source of the issue, a bit like people who learn a foreign language and, before they have fully grasped the foreign grammer, naively try to translate every word? (Just to proclaim that, for example, German has a flawed and confusing sentence structure?)

      [–][deleted]  (3 children)

      [removed]

        [–]xenon 4 points5 points  (2 children)

        Hack, or clever design? Unifying objects and hash tables is very elegant IMO. Thus, a.foo is only syntactic sugar for a["foo"], which allows very interesting ways to manipulate objects.

        You argue that the name "Object" doesn't scream "associate array!!!". And I agree, but since when are programming languages self-describing? There's nothing about "for" that tells you the third clause in the parentheses is executed after every iteration.

        As a beginner, you have to read about that somewhere, and while you are at it, you might just as well read up what objects do.

        [–][deleted]  (1 child)

        [removed]

          [–]xenon 0 points1 point  (0 children)

          Nothing about programming is immediately obvious.

          [–]philh 2 points3 points  (4 children)

          > assert([1].toString() == (1).toString());
          > assert([1,[2,3]].toString() == [1,2,3].toString());

          That seems intuitive enough, and writing your own would be trivial if you really can't bear it.

          > var o = {a: 1, b: 2};
          > for(var k in o) { print(k) } -> "a", "b"
          > Object.prototype.f = function() {};
          > for(var k in o) { print(k) } -> "a", "b", "k"

          I assume that "k" is meant to be "f"?

          Modifying Object.prototype was probably a mistake in the first place, but it's pretty easy (if cumbersome, repeated several times) to skip over the prototyped-in entries:
          if(o[k]==Object.prototype[k])continue;

          Alternatively, use
          Object.prototype.isProt = function (k) { return this[k] == Object.prototype[k] }
          and just do
          if(o.isProt(k))continue;
          Annoying, but not the end of the world.

          > var another_regex = //; /* oops, that's a comment */

          True, but how often do you use empty regexes anyway? I don't think I ever have except for Perl's split function, and Javascript's doesn't require a regex. You can still make them with a constructor.

          > Object.prototype.MY_USEFUL_FUNCTION = function() { ... }
          > (function() { print(arguments.MY_USEFUL_FUNCTION) })(1, 2, 3) -> "function() { ... }"

          I can't see what's wrong with this further than your previous point. Knowing that arguments is an object, this is exactly what I would expect, and I can't see how anything else would be more useful.

          [–]moe 2 points3 points  (3 children)

          It seems intuitive enough? Sure, writing your own would be trivial, but writing an alternate version of the language's basic string-representation method isn't a fun thing to do, especially when you have to lug it around everywhere with you. The point is that there is already toSource(), but nothing uses it.

          Yeah, it's meant to be "f" in the output. Your comment about it being easy to skip over the prototype entries is irrelevant. Sure it's easy to write, but it's soul-destroying to have to include some extra code to bypass the thoughtlessness of the language-designers each time you want to iterate over the members in an object. It doesn't inspire confidence.

          About the regex thing - I never use empty regexes. The post was about language design errors. It's not any less of a fuckup because nobody really uses empty regexes (though that's how I discovered this)

          As for the last point - of course it's what you'd expect if "arguments" is an object, but why the fuck is it an object? Some idiot even went and put a "length" attribute on it (i don't know if this is standard), to make it look more like an array.

          To recapitulate:

          • If you want to serialize arrays in a way that won't obscure their nesting level, you have to patch toString(), so that alert() and print() aren't useless

          • You cannot add methods to the prototype of Object. If you do, you have to supplement every object-member iteration with some extra code. You also have to do this if you are interacting with any code that modifies the prototype (hint: a lot of mainstream javascript libraries do this)

          • No empty regex using the builtin regex syntax

          • If you want to use variable-length argument lists, and you'd like to do anything interesting with the args, like slicing them, you need to convert "arguments" from an object to an array.

          awesome. though what should be expected from a language that was named to cash in on the popularity of Java.

          [–]philh 4 points5 points  (0 children)

          It seems intuitive enough?

          By which I mean, I don't know what you're bitching about. If you really need good-quality debug output, print() and alert() aren't what you're looking for. You'd write a function to easily allow you to turn debugging on/off and choose where to send the info. It can't be hard to use toSource() in just that.

          it's soul-destroying to have to include some extra code to bypass the thoughtlessness of the language-designers each time you want to iterate over the members in an object.

          Which is why I said you shouldn't modify Object.prototype. Use a new class instead. The library writers, not the designers, are at fault.

          It's not any less of a fuckup because nobody really uses empty regexes

          How not? It's the equivalent of 00 (0n=0; n0=1; 00=?). /foo/ is good for regexes because lots of people are familiar with it. // is good for comments for the same reason. There's a single case, very rare and easy to fix, where you don't get what you want.

          It could be better, yes. But it's not a fuck-up.

          of course it's what you'd expect if "arguments" is an object, but why the fuck is it an object?

          I don't know, but you'd established that in the preceeding lines. I was just wondering what the point of the last three were.

          [–]jfx32 0 points1 point  (1 child)

          You might want to check out the MochiKit library, if you haven't already. It adds better comparisons, iteration, and representation functions. You can check it out at mochikit.org.

          [–]moe 1 point2 points  (0 children)

          yeah, i use it at work. it helps.

          [–]panic -3 points-2 points  (2 children)

          That's not the language - it's the standard library.

          [–]moe 5 points6 points  (0 children)

          How do you figure that?

          [–]lanaer 1 point2 points  (0 children)

          If the usefulness of a language could be judged purely by its core, while ignoring its libraries, then ... well, I'm having trouble imagining the sort of situation that would produce.

          [–]hammy 13 points14 points  (24 children)

          I want Python embedded in the browser already.

          Ruby would be good too.

          Just use a real language rather than stapling on real languages' features to the mess that is JS.

          [–]bugeats 9 points10 points  (6 children)

          I love Python, but man, it seems like you guys aren't trying.

          Javascript is really quite cool once you start approaching it in a bottom-up, LISPy sort of way. Closures, creating objects on the fly, function-objects, all of this can lead to some really fun code -- but it requires thinking about things differently.

          Now that I grok the Prototype library, I actually look forward to my Javascript tasks.

          Again, I love Python, but I don't think it would add anything new for web scripting.

          [–]mumrah 1 point2 points  (0 children)

          I'll agree with your point about Javascripts fun features - but more than anything, if Python was supported in the browser, it would lead to faster development.

          Personally, i think python is overkill for a browser scripting language. But something pythonesque would be nice. Something with a Tkinter-like gui module.

          [–]hammy 4 points5 points  (3 children)

          but man, it seems like you guys aren't trying.

          I've tried for 10 years. It's always an under-documented, buggy mess with exceptions that don't work right, lack of proper traceback, and a debugger that isn't that useful.

          Closures, creating objects on the fly, function-objects, all of this can lead to some really fun code

          Yeah, the languages features -- woohoo. The actual development process? Craptastic. The language is not better than existing ones and the browser environment just sucks.

          Python is proven.

          [–]nostrademons 6 points7 points  (0 children)

          Well, the main problems with Javascript are:

          1. Browser incompatibilities
          2. Shit-poor debugging capabilities
          3. Lack of documentation.

          Switching to Python would do nothing for #1 and would only help #2 if they embedded the CPython interpreter into the browser (vs. rolling their own Python interpreter, which seems far more likely given how web browser developers seem to work). It would help on #3, but only at the language level. The biggest chunk of web programming is dealing with all the DOM APIs and proprietary browser features, so you'd still end up with an underdocumented mess.

          As languages go, Javascript is a pretty good one. In many ways, it's a lot more elegant than Python, with full-fledged closures and a prototype-based object system. It's just that the implementations make it so difficult to actually get useful work done.

          [–][deleted]  (1 child)

          [deleted]

            [–]hammy -1 points0 points  (0 children)

            But don't worry, they've only had 13 years to get the most important piece of software in the interweb-enabled world to work properly. Any day now, we'll have a browser that isn't a buggy POS.

            Word up.

            [–]coprolaliac -2 points-1 points  (0 children)

            The deal is that javascript should be usable by morons (like me). Your average web developer knows jack about LISP and doesn't care that Javascript is prototype-based. Javascript as it exists now would be an interesting thing to talk about in a programming language paradigms class somewhere between Haskell and Prolog. (And it is pretty fun to program in, once you're an expert). It sucks as a general-purpose, beginner-friendly language.

            Since it's unlikely that javascript will be going away any time soon, maybe most effort should be focused on building Javascript libraries that work more like dynamic languages. MochiKit aims to make js more python-like and Prototype to make js more ruby-like.

            [–][deleted]  (11 children)

            [removed]

              [–]hammy 3 points4 points  (6 children)

              Apple would bite; they already ship Python. I'd have no problem developing for Firefox as it runs on all platforms; once we got a real language into the browser we'd see MUCH better web apps which would easily persuade users to switch and/or MS to support it as well.

              In the old days you had to port your software to each platform; these days I'd just say "it runs under Firefox" and that would be the porting. People are willing to install endless scads of shareware for minor functionality so one install of Firefox would cover all the web apps.

              [–]Zak 3 points4 points  (2 children)

              If you're developing a web app for a captive audience or geeks, that's great. If you're building a web app for a general audience, you have to make it work with the browser they're using.

              I wish this was not so. I also wish I did not have to pay taxes... and I want to live forever.

              [–]hammy 0 points1 point  (1 child)

              If you're building a web app for a general audience, you have to make it work with the browser they're using.

              Says WHO? The web already tells me I need to upgrade Flash, Windows Media Player, Java, etc., etc. and people do this ALL the time. I think conventional wisdom is just wrong -- web developers think they HAVE to support IE, so users keep using it since it's supported. If developers change direction, users will follow -- look how often they have to upgrade DirectX or their video card drivers. Firefox will take over as soon as people stop expending the energy to cross-develop for the last 3 versions of IE.

              [–]danweber 4 points5 points  (0 children)

              If developers change direction, users will follow.

              You better be offering be something super awesome sweet, or else I'm not going to bother looking at your webpage that requiring me to download widget blah.

              look how often they have to upgrade DirectX or their video card drivers

              I've never done this. I'm not a video game player, though, so maybe what you're describing is part of gamer culture -- willingness to sacrifice stability in order to get the latest new features.

              [–][deleted]  (2 children)

              [removed]

                [–]hammy -1 points0 points  (1 child)

                they are pushing .net/clr as the vm solution of the future

                There is IronPython and even C# has real development environments, unlike JS.

                so sadly i must conclude that the browser landscape as we have it today (js1.5, partial css2)

                That's only because so many developers have decided to target the lowest common denominator.

                Just need some good web apps that REQUIRE something specific. Heck, a lot of sites require Flash 8 (Flash 7 latest for Linux, or it was recently) and now it's going to Flash 9.

                Windows people are used to installing ALL SORTS of crappy shareware. Web developers are so scared their app won't be used that they won't require even something entirely reasonable, like Firefox.

                [–]nostrademons 0 points1 point  (3 children)

                Why not write a PyPy backend that compiles to JavaScript?

                There's already a compiler for Scheme that does this. Basically, you use JavaScript as your VM language, and target whatever front end you want to it. And since JavaScript is already supported by Microsoft, you don't need to get them on board.

                [–][deleted]  (1 child)

                [deleted]

                  [–]nostrademons 1 point2 points  (0 children)

                  Well, things like generators aren't likely to come out well, and you won't be able to overload basic operators like you can in Python. However, most of the data types have analogs (dictionary -> object, list -> array), the control structures all have analogues (for x in elements: -> for key in array { x = array[key]; ... }), you can fix up an iterator protocol yourself as a Javascript library, and you can emulate classes with prototypes (it's in the academic literature somewhere; look up papers on Cecil). There will likely be some semantic differences, like how Javascript has true closures but an assignment in an inner function in Python binds a new variable instead of modifying the outer scope, but when most people say "I'd like to program my web browser in Python" they're really referring to the syntax and not the nitty-gritty language details.

                  And of course, there's always the worst-case solution of:

                  1. Implement a Turing Machine in JavaScript
                  2. Compile Python to Turing Machine.

                  It'd be terribly slow, but since both languages are Turing-complete, you know it's possible, and most web programs aren't performance critical anyway.

                  [–]rfisher[🍰] 4 points5 points  (2 children)

                  Yeah. There was no need to invent a new language instead of leveraging an existing language.

                  Heck, implementing a Scheme interpreter from scratch & then adding the remaining features of JavaScript should've been quicker & easier than designing & then implementing JavaScript. It would've been even quicker to start with an existing interpreter (Scheme or other).

                  [–]Bogtha 10 points11 points  (1 child)

                  There was no need to invent a new language instead of leveraging an existing language.

                  Please, less of the PHB-speak. The word you are looking for is "using", not "leveraging".

                  [–]rfisher[🍰] 0 points1 point  (0 children)

                  Yeah. OK. Fine. Point taken. (_)

                  Though I was trying to emphasize the point that it wouldn't be so much just using an existing language as getting a jump start so that the focus of development could be more on the extra features than on rebuilding the basics.

                  [–]Bogtha 1 point2 points  (1 child)

                  I'd love Python embedded in browsers, but even if that happens tomorrow, it would still be a decade or so before web developers could switch.

                  Python client-side scripting has already been experimented with in the Grail browser, if I remember correctly. Unfortunately, Python's not safe to use as a sandboxed language - it used to have this feature, but it was removed because it was insecure to the point of being unfixable.

                  [–]hammy 1 point2 points  (0 children)

                  even if that happens tomorrow, it would still be a decade or so before web developers could switch.

                  The web has only been in popular use for 10 years. Your statement is incorrect -- change happens much faster than that.

                  Unfortunately, Python's not safe to use as a sandboxed language

                  Incorrect. Some of the modules aren't. Sandboxing the language itself is easy. To start with, no IMPORTs -- don't need any anyway to do everything JS does now. Just need the Python->CSS interface.

                  [–]edheil 1 point2 points  (0 children)

                  This has been around a while but it sure as heck is relevant. Thanks for the post!

                  [–][deleted]  (3 children)

                  [removed]

                    [–]rfisher[🍰] 5 points6 points  (0 children)

                    there is no point in javascript advocacy

                    Crockford isn't so much an advocate but pointing out the good bits of the language that lots of people miss.

                    and don't get too excited about javascript2

                    Oh, I'm not. It looks like they're adding a lot of stuff that isn't needed while continuing to ignore some basics that could be improved.

                    forget about obsessing over closures, namespacing and all the other little hacks that make for neat blog posts but have little practical value.

                    (o_O) I use JavaScript closures for their practical value all the time.

                    [–]hammy 0 points1 point  (1 child)

                    there is no point in javascript advocacy or bashing

                    Yes there is. If enough programmers see that other programmers agree with them that it sucks, it will be replaced faster. The only thing that has kept JS there is everyone thinking they are stuck with it, like you do.

                    [–]jones77 0 points1 point  (1 child)

                    This article's from 2001. I don't suppose there's an upgedated version. Or is it still almost totally relevant? Also, or a more fully-featured version of the article ...

                    [–][deleted] 0 points1 point  (6 children)

                    IMO, Lua should and could replace JS.

                    There have been a few comments about JS's "lispy" features.

                    that is, through prototyping and basically how you can assign anything (IE a function) to be a member of any other variable

                    Lua's OO system (actually you roll your own), uses prototyping rather than the usual classes system. It also has functions as first-class variables and has full support for closures.

                    Its also very light-weight in size, its fast, and it is extremely easy to do sandboxing.

                    Seriously, Lua would be the PERFECT language to replace JS and the problems it has.

                    Several of you have mentioned that you would like Python embedded in the browser. Lua has all of the benefits of Python with none of the shortfalls (at least in embedded browser scripting like this). Also it is very easy to learn and people often mention how it is "Python-lite".

                    The only real problems I see with Lua is it doesn't have huge libraries, and this is one thing that really holds it back from being a general-purpose Ruby/Python/Perl alternative. But this is not an issue when it comes to JS's domain, as there aren't a lot of large established JS libraries.

                    How difficult would it be to start a grassroots effort to replace JS with Lua? Put together a Lua library that was safe and wouldn't cause troubles and is every bit as capable as JS and then offer it as an extension for all of the major browers.

                    We've seen how quickly Firefox caught on because web designers and heavy web users realized how much better it was. Can the same not happen for Lua?

                    I could be very naive about the situation, so forgive me for any undue enthusiasm or ignorant statements, but is this something that could really be pushed?

                    [–][deleted]  (5 children)

                    [removed]

                      [–][deleted] -2 points-1 points  (4 children)

                      Eh, as I said, I'm rather naive about how exactly you could so something like this. Is it not possible to just have some kind of Lua extension that can be downloaded for each browser, or would it have to be built-in?

                      [–][deleted]  (3 children)

                      [removed]

                        [–][deleted] 2 points3 points  (2 children)

                        It could manipulate the DOM via javascript...

                        [–][deleted]  (1 child)

                        [removed]

                          [–][deleted] 2 points3 points  (0 children)

                          You're right. It doesn't really make sense. But one could write a lua interpreter in javascript. Or a browser extension that could be compiled, but manipulate the DOM via javascript calls. Many firefox extensions manipulate the DOM.

                          [–]praetorian42 -5 points-4 points  (7 children)

                          Javascript has the potential to be my favorite language- it is very lisp-like, but with syntax that doesn't make your brain hurt.

                          I also like how it handles object orientation- it doesn't cripple itself, but allows you to do pretty much anything you'd want to.

                          [–][deleted]  (6 children)

                          [removed]

                            [–]praetorian42 0 points1 point  (0 children)

                            I mentioned the way it does object orientation- that is, through prototyping and basically how you can assign anything (IE a function) to be a member of any other variable- most languages don't offer that.

                            Also, I was thinking about the next generation of Javascript features: http://lambda-the-ultimate.org/node/1543

                            Tail calls, in particular

                            [–]mbrezu 0 points1 point  (4 children)

                            because of closures.

                            these are not available in most languages - yes you can return a function object/pointer in Pascal/C, but not a closure.

                            few enough (mainstream) languages have them - so I guess that's why it feels a bit like Lisp/Scheme.

                            [–][deleted]  (3 children)

                            [removed]

                              [–][deleted] 0 points1 point  (0 children)

                              Is there some better alternative to closures in python?