

Javascript in Ten Minutes - buluzhai
http://javascript.infogami.com/Javascript_in_Ten_Minutes

======
boucher
[https://developer.mozilla.org/en/a_re-
introduction_to_javasc...](https://developer.mozilla.org/en/a_re-
introduction_to_javascript)

This continues to be pretty much the best JavaScript reference on the web.

------
tumult
I've had a few beers, so I'm just going to come out and say it: JavaScript is
a terrible language. The best thing it has going for it is that it's Turing
Complete.

"But wait!" you cry, "it's dynamic! It has lexical scope and lambdas!
CLOSURES!" Too bad tail call elimination isn't in the spec. Or any kind of
optimization on continuations or recursions. Yay running out of stack, tons of
fun.

I'll write a book called "JavaScript: the Best Part" and it will be one page
long with "Parenscript is the best part of JavaScript" printed on it, with
"(pray you don't end up 10-feet deep in a call stack)" in smaller type
underneath.

Maybe I should lay off the India pale ales and comments.

edit: I had to use JavaScript for something a few weeks back, it was like
being hit on the head with a hammer wrapped in a damp cloth. Let me show you
what I mean: <http://emgio.com/wow.png> There are so many things wrong with
this that I had to take a picture, which I now show to people whenever they
try to argue in JavaScript's defense. The blue text is interpreter input and
black is the return.

Actually, JavaScript makes a fun benchmark race I guess, just because it's so
ridiculously hard to write an optimized interpreter for.

~~~
axod
You should learn some more javascript. The language itself is pretty sweet.
Individual implementations vary.

Your image just shows you don't understand very much about the language. It's
not "wrong" once you understand what it's doing and why. Show it to anyone who
understands what is happening, and you'll look quite foolish. It's not
massively complex once you read "Javascript: The definitive guide (O'Reily)" -
the best book on js by a mile.

    
    
      var obj1 = {};
      // var doesn't return anything, so the interpreter shows 'undefined'.
      var obj2 = {};
      // same again
      obj1 == obj2;
      // Well no, they're different objects. So you'll get false
      var thing = {};
      //
      thing[obj1] = "hi";
      // OK this is an odd thing to want to do, but you're doing it anyway.
      // You're using an *object* (obj1), as a key.
      // The js thinks you're idiotic, but complies by calling the .toString() method,
      // and gets "[object Object]" or similar by default.
      // (You're free to override that on your object).
      thing[obj2]
      // Once again, you're using an object as a key
      // and acting surprised that js has changed it into a string.
      // So, you created an object and set thing["object Object"] = "hi"
    

So instead of "Wow! js is retarded", my response to that code would be "Why is
he trying to use objects as keys? and why is he surprised when js converts
them to strings?" I recommend the above book to clear up things like this.

~~~
tumult
Read it again, the problem is that it accepts it silently and does not
indicate any sort of irregular behavior in an operation that shouldn't work
that way. It just does it and then fails weirdly in the future.

I fully understand how equality works in JavaScript (especially after making
the mistake pictured.)

Also, the existence of an "===" operator should be troubling. Many people
writing JS don't even know it exists.

edit: when you extend your reply in a large way, please append it with "edit:"
or just make a new reply, thanks :]

~~~
axod
Why shouldn't it work that way??? It's silently doing type conversion for you
- from an object to a string. That's desired behavior. Just as most languages
presented with "foo"+12 would silently convert 12 to a string via the
toString() method.

What way do you think it should work? :/

An example of more sane usage:

    
    
      >>> var myv={}
      >>> var foo={toString:function(){return "12"}}
      >>> myv[foo]=34
      34
      >>> myv[12]
      34
    

>> "Also, the existence of an "===" operator should be troubling. Many people
writing JS don't even know it exists."

You can't fault a language because some people don't make the effort to learn
it properly.

~~~
tumult
I'm a karma burning mood so I'll keep going :]

This is the main problem I have with it; it's a very dynamic language but in a
totally dangerous way. It should hash based on an object's identity or
something; as it stands, there's no way to do that in JS without bolting your
own junk on top, as a result you can't do real object<->object associations in
JS.

Python for example has well-defined and useful behavior when you shove
something into a dict type as a key, for strings it will hash based on the
string value, for some other things it will uses identity, etc., and you can
overload it (which you can in JS too of course, as you showed.)

~~~
axod
_maybe_ the default toString() should be a unique ID, as it is in for example
Java, but it's not really a big deal. How often do you need object A->object B
associations like that? Far easier to just put a pointer in all the object As
to point to object Bs, and then put the object A's in an object/array.

Your use case is not something I've ever needed to be honest, and if you need
it, it's simple to build it out yourself. For example, in an object
constructor, just replace the toString() to return a unique ID for that
object. A line of code :/

It's only dangerous when you don't understand what is happening. Why didn't
you research why your image example was confusing you? As I say, read the
book.

~~~
tumult
_How often do you need object A- >object B associations like that? Far easier
to just put a pointer in all the object As to point to object Bs_

This gives us an equivalent mapping, but unfortunately it alters the original
object by adding a property to it. This sucks for two reasons; one is that the
names might clash with a property that something else has set on that object,
so you end up creating terrible names to avoid collisisions like
someObject._prviate_associatedOtherObject or something, and then you have to
make sure to destroy it when appropriate. It gets more hairy if you need
multiple relations between the same objects. The other problem is that when
you enumerate an object, now that property will show up. Gross. Yes, I know
about the boilerplate you use to make enumerations in JS safe; my argument is
that JS sucks as a language, and the necessity of stuff like this contributes
to it.

 _For example, in an object constructor, just replace the toString() to return
a unique ID for that object. A line of code :/_

The Cappuccino/Objective-J guys at 280North have to do something similar (grep
for OBJECT_COUNT++ in the source to see what I mean) in order to add identity
to Obj-J objects.. but what if you didn't instantiate the object yourself? And
I think this is the case where you'd be _most_ likely to want to perform a
mapping on an opaque object.

~~~
tumult
Sorry I'm replying to my own comment here, I don't have to time to wait for
the next exponential decay on the reply button showing up before I have to
leave. I'm actually replying to axod's comment on this same level.

Well here's an example, I have an AJAX instant messenger app. Due to the
protocol it talks on, multiple users may have the same name (a reasonable
request, I think.) When a contact on a user's buddy list connects, the JS
library in charge of talking to the server passes an opaque ChatUser object
(or whatever) to any registered callbacks. So, I write a second set of JS
stuff to manage the GUI, like the window for the buddy list, etc., and
register it to receive the callbacks from the protocol manager. When I get a
user that connects, for example, I should probably create an html span with
that user's name and away status in the div that holds the buddy list.

Now, when a buddy changes his/her away state, the protocol manager will tell
the registered callbacks that a ChatUser has changed status (or you can
register for a callback on the ChatUser object itself, either works.) We need
to change the status message in that user's span. But how do you find the span
we need to modify? The ChatUser object is mostly opaque except for a few
documented calls we can make on it (getName, getStatus, etc). Setting new
properties on it is probably a bad idea, since we don't know what the original
library is going to be doing with it.

In another language you can just associate the span's identity with the
ChatUser through a map or dictionary. But you can't associate based on
identity in JS, so you're left setting some crazy property on the ChatUser
instance and hoping it doesn't collide or cause problems. We can't base it on
the ChatUser's name, because what if there are multiple Joe Browns in the
contact list?

It's a contrived example, but I hope it illustrates the importance of
associations. There are multiple workarounds for this situation. But they
aren't elegant, which is why I think JS sucks :]

~~~
axod

      1. You would keep a pointer to the span, in each ChatUser object.
      2. You would have *some* unique ID passed from server->client
         to identify which user its talking about. A session ID say.
         this could be used to lookup the ChatUser object.
    

>> "It's a contrived example, but I hope it illustrates the importance of
associations. There are multiple workarounds for this situation. But they
aren't elegant, which is why I think JS sucks :]"

Nope, and I actually think your proposed method - mapping ChatUser->span is
incredibly ugly and inelegant. Horrible design. A ChatUser object should know
what UI elements it is in control of directly.

~~~
tumult
Why? The original library does not deal with GUI at all. The ChatUser object
does not need to know what GUI HTML elements it's associated with. One
component of a piece of software extending another should not have to tamper
with the original; this is just bad design in general, not OO or any specific
flavor.

