Souders: All right, welcome, everyone.
It's great to see a big crowd here.
My name's Steve Souders.
I work here at Google on latency.
And I wanted to do a couple plugs for these talks.
I'm trying to see about starting up a series
of tech speakers coming in.
So a couple weeks ago we had John Resig come in
and you can see that talk
up on the Google developer channel up on Google code.
And next Thursday at 11:00 A.M. right here
is Rob Campbell who works at Mozilla
and he's one of the people leading the Firebug effort.
And he's gonna do a talk next Thursday at 11:00
right here on Firebug and the new releases
that are coming out and some of the new features.
And-- But today--
So today we have Doug Crockford.
Um, I worked with Doug at Yahoo.
That's where I met him.
And I remember the first time I met him
and he told me his name, I said,
"I know that name somewhere. I know that name somewhere.
Oh, yeah, I've been using the stuff on your website a lot."
And so I was really excited to meet him.
And he's a really nice guy.
I enjoyed working with him at Yahoo.
Um, I--
I, uh, have a little bit of hesitation
because when my book came out, it did pretty well.
And then Doug's book came out and just kicked my book's butt.
And so I just checked.
And I'm, like, at 6,000 and you're at, like,
4,000 on Amazon sales rank, Doug.
So that's really good.
And I believe that this talk is largely based on his book,
"JavaScript: The Good Parts."
And so we'll run for about an hour
and have time for Q and A.
So without any further ado,
please help me welcome Doug Crockford.
[applause]
I forgot.
Here's your Google tech talk goodie bag.
Crockford: This is what makes it all worthwhile, right here.
[laughter]
So, thank you, everybody.
I'm Doug Crockford from the Yahoo.
And I'm here today to talk about the good parts.
Now when I first started talking about JavaScript,
there were a lot of people who just could not accept the fact
that JavaScript has good parts.
But, in fact, it does.
But it's not well understood. Even now.
JavaScript has become probably the most important
programming language in the world.
There's more JavaScript processors
on more computers than anything else
by a very large factor.
But despite that, JavaScript is not held
in very good esteem, even within
its own programming community.
For example, the C# community loves Anders.
And the Java community loves Gosling.
And the PHP community loves Rasmus.
But in the JavaScript community, there is no love.
And there should be.
And I think it indicates a lack of understanding.
That's why JavaScript is still the world's
most misunderstood programming language.
It's the only language that I'm aware of
that people feel that they don't need to learn it
before they start using it.
[laughter]
It kinda looks familiar and yeah, yeah, yeah, yeah.
I've seen this before. I know how this works.
In fact, it works in a really radically different way.
It just looks very similar.
And then when people misuse it as inevitably they do
because they don't know how it works,
they get angry at it, and misunderstand it.
Which is a shame because there's actually
good stuff in this language.
And because it's everywhere, JavaScript is now becoming
the virtual machine for the world,
which is a really odd mission for this
little misunderstood language.
You know, you're doing it here at Google with the GUID.
And there are lots of other examples
of the same kinda crazy thing.
You know, it amazes me the lengths that people
will go to to avoid having to learn JavaScript.
But it's learnable and you can actually
write good programs in it.
And like everything else, knowing what you're doing,
you know, makes a difference.
And so I'm here to enlighten the world about JavaScript.
JavaScript is a language of many contrasts.
It contains some of the best ideas ever put
into a programming language.
And it contains some of the worst ideas
ever put into a programming language.
And a lot in between.
There's no other language which has this amazing range
of the ridiculous and the sublime.
Um, if you look at the community of people
who use JavaScript, it has the broadest range
of programmer skills of any programming language.
We've got people at the very high-end doing computer science
in this language, which it does really well
'cause it's basically a scheme with C syntax.
And we've got cut-n-pasters who don't even know
that they're programming, who are putting stuff together
and making it happen.
If you gave those kids Java compilers,
they would never get "Hello World" running,
but they can work with JavaScript.
So the language has amazing expressive power
and it supports everybody in between.
I contend there is no other programming language
that can support this really broad audience of users.
And I'll offer that as further evidence
that this language is getting something right.
Which again, may be surprising to the people who think
this language didn't get anything right.
One of the reasons people think that is that
they have a lot of complaints about it.
And I think these complaints are all valid
and I'd like to go through them one at a time.
The first one is that JavaScript is not a language I know.
If you're programming in any environment--
the desktop or embedded systems or the server--
generally, you get to pick what language you're going to use.
But if you're writing in the browser
or if you're writing in one of the applications
that has embedded JavaScript in it,
you don't get a choice.
You have to use JavaScript.
And a lot of people get resentful about that.
You know, "Why should I have to learn this stupid language?
"I already know lots of other good languages.
Why can't I use one of those?"
You can't.
Um, and so they...
try to write without learning the language,
which I think is really a bad thing to do.
My advice is man up and learn the language.
If you need to be writing in JavaScript,
there's nothing like knowing what you're doing.
Second complaint.
The browser programming experience is awful,
which is absolutely true.
But that's not JavaScript's fault.
I contend it's the DOM's fault.
The DOM is one of the worst APIs ever imagined
and that's what you have to use when you're using the browser.
Fortunately, there are a lot of Ajax libraries available now
which all do an amazing job at correcting the DOM model
and turning it into something that you can actually
write good applications in.
So, uh, there is a solution to that.
I'm hoping eventually we can push that solution
back into the browser.
But for now, the Ajax libraries work really well.
YEY, I'll mention that one. Comes out of Yahoo.
It's actually very, very good.
I think maybe the best of them.
There are lots of others that are also very good.
There's a complaint that it's not fast enough.
And in the browser, that's mainly because of the DOM again.
If you look at the fraction of time
that your program spends running,
a tiny fraction of that is actually running
in the JavaScript interpreter.
Most of the rest of it is wasting time
in the DOM interface.
So if you could somehow make your programs
go infinitely fast, most web applications
are gonna look about the same.
There are other applications for which having
a faster language would actually be a benefit.
And so I'm happy to see that mainly, I think,
because of leadership from Google,
we're now starting to see higher performance
JavaScript entrants, which I think
is really, really cool and very much to be encouraged.
Although, practically, I don't think it's gonna make
much difference to web applications for a long time.
Then finally, there's a complaint
that the language is just a big pile of mistakes.
And I contend, no, it's not just a big pile of mistakes.
[laughter]
That hidden under a huge steaming pile of good intentions
and blunders, there is an elegant, expressive
programming language because JavaScript has good parts.
And if you can recognize those parts
and use those parts exclusively and avoid the bad parts,
you can actually write good programs in this language.
And I'll offer again, as evidence of that,
that JavaScript is succeeding very well
in an environment where Java was a total failure.
I don't know if anyone here remember Java applets.
How they're gonna change the world?
Didn't happen.
Crap.
Java turned out to be an okay language
and found a niche in the server
where it's doing pretty well.
But it was absolutely awful as a client programming language.
JavaScript is doing really, really well there.
The influences on JavaScript were Self,
from which it borrows prototypal inheritance
of dynamic objects.
Dynamic objects are a really clever thing
and they worked really well in this language.
From Scheme, it gets lambda, which is maybe the best idea
in the history of programming languages
and loose typing, which is pretty controversial.
The style of most languages today calls for strict typing.
The theory being that strict typing allows for
the compiler to check a large class of errors
at compilation time avoiding--
Catching any error early reduces the cost of the errors.
So that's a good thing.
And JavaScript doesn't have that.
So in JavaScript, any variable or any parameter
can contain a value of any type.
And that's really frightening to someone
who's coming from a strongly-typed tradition.
Like, "How can I have any confidence
that anything's gonna work right?"
It turns out that strong-typing
doesn't absolve you of the need to test.
You still have to test everything,
'cause there's an even larger class of mistakes
that type checking doesn't find for you.
And I found in my own practice that the amount
of testing that I have to do, writing in Java
or writing in JavaScript, is about the same.
That those type errors get found really quickly anyway,
so they're not really a problem.
The areas that are a problem,
the ones that keep me up at night,
um, type safety wouldn't have helped me there.
The benefit of having loose typing
is you don't have to mess with the type system.
And so that turns out to be liberating.
Your programs tend to be a lot smaller and a lot simpler.
So which one do you like? Well, it doesn't matter.
If you're working in JavaScript, it's gonna be loosely typed
and that's just the way it works.
From Java we get syntax, which is a source
of a lot of problems because it's basically
the C family of syntax, which we've all learned
to deal with.
We've gotten so good at it that we don't even recognize
anymore how defective it is.
But because JavaScript is used by beginners,
those problems are intensified.
And then finally, from Perle, JavaScript gets
a really horrendous regular expression notation.
So before we get to the good parts,
let me tantalize you with some of the bad parts.
The worst part by far, global variables.
JavaScript doesn't have a linker.
So the way compilation units get bound together
is they all get tossed in a common global namespace
where all the variable names can collide
and interfere with each other.
It has terrible reliability problems.
It has even worse security problems.
You've all heard of cross-site scripting attacks.
Those attacks are fundamentally enabled
by JavaScript's use of global variables.
JavaScript uses + to both add and concatenate.
It got that little bit of overloading from Java.
In Java, it wasn't too bad because it's strongly typed
and so you could predict which one it's going to do.
In JavaScript you can't.
So this is a very common source of errors.
Semicolon insertion was something intended to make
the C syntax easier for beginners.
C syntax, the rules for where a semicolon goes
are kind of complicated.
You really have to understand the syntax
of the whole language in order to understand where to put them.
So to make it easier for them, JavaScript says,
"We'll put them in for you so you don't have to use them."
The way it did that was when the compiler gets an error,
it backs up, looks around for a line feed,
turns it into a semicolon, and then tries again.
That should freak you out.
[laughter]
It sometimes puts them in the wrong place.
Sometimes doesn't put them in places where you'd expect.
My advice?
Figure out where the semicolons go.
Put 'em in the right place.
You'll be much better off.
JavaScript has a typeof operator
which allows you to determine if the typeof a value
is a string or a number or something like that,
which is really good.
If you ask it what the typeof an object is,
it says it's an object.
Great.
If you ask what the typeof an array is,
it says it's an object, which isn't very helpful.
If you ask what the typeof null is,
it says it's an object, which is wrong.
It has a with statement, which was well-intentioned
but doesn't work right.
I highly recommend you avoid it.
Simply by being in the language, it causes programs
to be a lot slower than necessary
whether you use it or not.
And similarly, eval is the most mis--
most misused feature in the language.
If you ever find yourself needing to use eval,
you're probably thinking about things in a really wrong way.
So step away from the computer, read my book,
and then take another run at it.
[laughter]
JavaScript has phony arrays.
In most languages, you've got an array,
which is a linear sequence of memory,
which is divided into regularly spaced buckets,
so you can do address computation
and very quickly get to an element.
JavaScript doesn't have anything like that.
In JavaScript, arrays are essentially hash tables,
in which the keys are turned into strings
and then hashed to locate the buckets.
This has a terrible performance penalty.
But it has an advantage in that it makes
the programming model quite a bit easier,
'cause you don't ever have to dimension an array.
Dimensions don't exist in this language.
It has a equality operator that does type coercion,
which turns out to be problematic.
I'll show you an example in a moment.
And it has too many bottom values,
which is a problem because beginners tend to get confused
by having all these things which almost mean the same thing
but are slightly different in their meaning.
So these are some of the consequences
of type coercion on the quality operator.
There are rules that govern this.
This isn't random behavior.
But it's certainly surprising behavior.
And the rules are not memorable,
so this all looks very mysterious.
Fortunately, the language has a triple equal operator,
which does not do type coercion,
so it would answer false to all these cases,
which is the right thing.
So I highly recommend--
Always use a triple equal operator.
Never use the double equal operator.
Just don't use it.
So one of the nice things about the dynamic objects
in this language--
If you ask an object for a property that it doesn't have,
you don't get an error, it doesn't throw.
It just returns to the undefined value,
which is really nice.
So you can, you know--
Reflection is just automatic on things like that.
So if you then ask if the thing is undefined,
then you can do something about it.
But because a lot of beginners don't understand
the difference between null and undefined,
they use null and they use the wrong comparison operator,
which often works.
It's the case of two errors that cancel each other out.
That's not a good way to write programs.
So the right way to write this program
would be to use the proper equality operator
on the proper value and now it'll work for all cases.
Here's another case where good features interact badly
in this language and I'll give you an example.
Objects can inherit from other objects,
which is good.
One of the interesting things about this language
is you don't have classes inheriting from classes.
Objects inherit directly from other objects,
which is really powerful, it turns out.
Objects can be members--
Functions can be members of objects, which is good.
That's how methods are created in this language.
And we have a for..in statement that mixes inherited functions
with the desired data members, which is not useful at all
and is a common source of errors.
So how did that happen?
There was a design question in the making of the language.
Should the for...in statement, which iterates
through all of the members of an object,
do a shallow skim of the object's own properties,
or should it do a deep dredge
going through its inheritance chain?
The decision was to do the deep dredge.
And I think the thinking was that if we do the shallow one
and what people really want is the deep one,
we're screwed.
They just can't get at that stuff.
Whereas if we do the deep one and what they wanted
was the shallow one, they can do the filtering themselves.
Except that they didn't tell anybody
that that's why they did it and that's how it works.
And so as a consequence, there's a lotta confusion
about how to use for...in
and how to attach methods to prototypes.
I think a better decision would have been
to not release the language until they had enough experience
with the language to know what the right answer was.
But to put it into historical context,
at Netscape, getting it right was not an option.
Which is why there's no longer Netscape.
Um, yes?
man: Isn't the real issue that people are using
objects as hash tables and they really aren't hash tables
because when you said they were, like, two strings
who get things you don't expect?
Crockford: Um, no, but we can get to that in the Q and A.
Um, so these are things which are wrong with JavaScript,
which are really wrong going all the way back to B actually.
But I'll talk about them here 'cause we're talking
about JavaScript.
We have the option of using blockless statements,
which is a bad practice.
It creates code which is more likely
to get damaged under maintenance.
So I recommend always putting the curly braces in.
It allows for expression statements
in which it can just have the name of a variable
or a simple expression and do nothing.
I think the reason for that was it made the specification
of the syntax a tiny bit easier.
They were able to save a production or two.
But as we're gonna see, it just messes things up.
The most often reported error in the language
is that 0.1 + 0.2 !== 0.3.
And this is not really a problem with JavaScript.
It's a problem with IEEE floating point.
That floating point is the only number type in the language.
Having just one number type in the language
turns out to be really nice, particularly
for a language that beginners use,
because there's a whole lot of compatibility problems
that just go away.
Everything is the same type.
But unfortunately, they picked the wrong type.
That you tend to do a lot of computations involving money
in this language and the sums come out wrong.
And generally when you're adding people's money,
people have an expectation that the results gotta be right.
And it's hard to do in this language.
Unnecessarily hard.
It has the increment and decrement operators,
which are very convenient but have been implicated
in buffer overruns and other security hazards.
I found in my own practice that when I use them,
I would tend to write code which was too tricky.
And code which is too tricky is too often wrong.
So in my own practice, I don't use them anymore at all, ever.
Just part of my discipline.
Finally, it has the switch statement.
The switch statement was modeled after the FORTRAN computed goto.
It has the property that one case can fall through
into the next case.
I'm gonna tell you later about a program I wrote
called JSLint which is a quality--
code quality tool for JavaScript.
One day someone wrote to me and said,
"You know, the language has switch statements
"and sometimes you can have one case fall through
"into another case and it's really difficult to see that
"when reading the code, you know?
"So could you have JSLint generate a warning
anytime that happened?"
And I thought about it deeply and I wrote back to him
and I said, "Well, there are cases
"where it's actually beneficial
to have that falling through."
And you could have a code indicating, you know,
whether you intended that or not but, you know,
that doesn't really work.
You know, so on balance, I think maybe it's better
just to leave it alone.
That it's actually a good thing
to have in the language.
Next day, the same guy sent me a bug report
that I had something that JSLint was misclassifying.
So I threw it in the debugger and it turned out
I had a switch statement that was falling through.
[laughter]
So in that moment, I achieved enlightenment.
There are these moments in your programming career
where you actually learn something.
Learning turns out to be really hard.
And in this case, I actually learned my lesson.
And so I now never intentionally
fall through in a switch statement.
And because of that I can now much more easily detect
when I accidentally fall through in a switch statement.
So as a consequence, I think my use of that statement
has improved significantly.
So you've been waiting for the good parts.
Here they are.
It's a short list but it's a good list.
At the top of the list is Lambda.
This came out of Scheme, which came out
of Carl Hewitt's work on the Actor model.
I think this is the best thing ever
to go into a programming language.
It's powerful, it's safe, it's smart,
it's good, it's flexible.
Great stuff.
JavaScript has dynamic objects, which means
you can take any object and at any time,
you can add a new property to it or remove a property from it.
You don't have to go to some class
and make another derived class in order to have an object
which is slightly different than the one you've got.
That turns out to be amazingly powerful.
Makes this language especially easy to use.
It's got the loose typing in it,
which some people look at as a severe disadvantage.
I think it's actually an advantage.
This language is better off, I think,
for having loose typing.
And it has object literals.
Object literals are a very nice notation for describing objects.
JavaScript's object literals were the inspiration
for the JSON data interchange format.
Um, there--
Inheritance is object-oriented code reuse.
And there are two schools of thought for how to do that.
There's the classical school, which is represented
by almost all present-day languages.
And there's the prototypal school,
which is represented pretty much just by JavaScript.
There are no other languages in broad use
which have this property.
Turns out the prototypal inheritance
is amazingly powerful but it's not well understood.
It's so powerful that you can program as though
it is classical and it mostly works.
You can't do the opposite.
You can't go to a classical language
and program as though it's prototypal.
So in prototypal inheritance, it's class-free.
There are no classes.
Objects inherit directly from other objects.
And in this language, an object contains a hidden link
to another object from which it inherits stuff
in a process called delegation.
Sometimes called differential inheritance.
So each object contains only what makes it different
from the object it inherits from,
and that allows for objects to be much smaller.
For a long time, the language was ambivalent
about its prototypal nature, so never included an operator
for actually making new objects
which inherit from other objects.
We're correcting that oversight in the next edition
of the language with object.create,
which will make a new object which inherits from an old one.
Um, it's not in the current browsers,
but it's easily implemented.
Until it becomes standard equipment,
you can realize it in this way.
What JavaScript has instead of this operator currently
is a weird trio of constructor functions,
prototype members, and a new operator,
which were intended to provide a friendly object--
or friendly classical-like notation
for dealing with prototypes.
But it didn't work.
The Java community smelled this immediately and said,
"That's alien.
That's clearly not something we like."
And so what it really did was confuse
what the language was actually doing.
Uh, so in--
As part of that sugar for trying to look classical,
JavaScript has a new operator, which is absolutely required
when you're calling a constructor function.
If you call a constructor function
without the new operator,
instead of creating a new object and initializing it,
your constructor will clobber the global object,
which is a very, very bad thing.
There is no compile-time warning
and there's no run-time warning for this.
So for this reason, I don't use "new" anymore.
I think it's just too dangerous.
So it's time to look at some code.
Here I'm gonna make a simple little function
called digit_name, which I'll pass it a number
and it will return a string which is the name of the digit.
So I've got an array of strings,
which I create using an array literal.
Very nice.
And then the function returns
looking up the argument in the array.
So everybody understand how this works?
All right.
Problem with this is names is a global variable.
So if there's anything else in my application called names,
either it's going to fail or my program's gonna fail
or we're both gonna fail, which is really bad.
Particularly as pages become really dynamic,
I may be linking with libraries I've never seen,
will never get a chance to test with.
I may be having to run with ads which I will never see,
which could interfere with my program.
So I want to--I have really good reasons
to try to avoid the global variables.
And the language gives us
a couple of options for doing that.
One approach would be I could define the array of names
as a private variable of the function.
And that works just fine.
So we have function scope in this language.
We don't have block scope, so you need to understand
the difference and do it right.
But having that, this will work.
So names is no longer a global variable,
so I avoid that hazard.
The problem with this is that every time
this function gets called, we're going
to reinitialize the names array.
Now in theory, an optimizing compiler
could detect this case and factor that out.
But today, nobody does that.
So I might want to write this function in a different way
to avoid that.
So one way I could do that would be
to put it in a closure.
So here I've got a function which is going
to return another function and the outer function
gets executed immediately.
Okay?
The inner function has access to the properties
of the outer function or to the variables of the outer function.
It will continue to enjoy access to them
even after the outer function has returned.
So this allows me to have--
So when it returns, the function goes into digit_name
and that function will have names bound
to the original array and will continue to have it
for as long as it lives.
This is an amazingly powerful thing
that this language does very, very nicely.
And we can generalize this into a constructor pattern.
So if you think of an application
or any kind of singleton, we don't have to make a class
in this language to make a singleton.
We can just make it.
And the proper--
The methods that that singleton has,
can enjoy private shared access to stuff.
We don't have to put it in global variables.
So I can--
Again, I've got a function which I'll execute immediately
and return an object literal which contains some methods
which will do useful stuff.
And those methods will have access to the private material
that the outer function provides for them.
We can take this and turn it into a constructor,
which is a very nice way, an alternate way,
in this language for making objects.
So here's the recipe.
Step one, you make an object.
And there are four ways we can make an object.
We can use an object literal. We could use "new."
I don't do that but you might.
We could use object.create to beget something
from an existing object.
Or we could call another of these power constructors,
which gives us another inheritance model.
Step two, we define some variables and functions.
These will become the private members
of the object that we're making.
Step three, we augment the object with privileged methods.
Privileged methods have unique access
to the stuff defining step two.
Then step four, we return the object.
So pretty simple recipe.
Let me turn the recipe into a template.
So step one, I'm gonna make a new object.
I'm gonna put it in a variable called "that."
"That" because it's reminiscent of "this."
And I can't call it "this"
because "this" is a reserved word.
Step two, I'll define a variable that will be secret,
be private, shared by these guys.
Step three, I'll create a privileged method,
which is a function which will have access
to the state of the outer function.
And step four, I return that, and that's it.
Really easy way to make objects
which can hide their stuff and be private.
So the reason this works is because
we have closure in this language,
which means that a function object contains
the function itself, which has a name and parameters
and a body and it has a reference to the environment
in which it was created or the context.
You know, which--
In this case is the stuff that was in the outer function.
This is a very good thing.
This is one of the best parts of this language.
Now concerning style,
if you get any two programmers together,
they could argue all day about matters of style.
Like should the curly brace be on the left or on the right?
And they may get really emotional about
which way it goes.
We feel very strongly about this stuff
even though we don't know why.
You know, we can agree that whichever we do,
we should be consistent.
But it's hard to find agreement
on should it be on the left or the right.
It's sort of like, "What side of the road
should we drive on?"
There's not a compelling reason
for why we should drive on the left or right.
As long as we all drive on the same side.
If we don't, then bad things will happen.
And we have a similar thing here.
So if you look at why people get emotional
about that stuff, where did the idea
of leftness or rightness come from?
You know, you could trace it down
to where they went to school
or what they learned on their first job
or are deeply impressed somebody early in their career.
They may give you a lot of reasons
for why the left side or right side is better than the other.
But they don't fundamentally know.
They just get really emotional about it.
Well, it turns out having them on the right side
is the right way and the left side is the wrong way
in JavaScript.
I can't testify for any other language.
But it is absolutely true for this language.
And I'll show you an example why.
So here we have a return statement
which is returning an object literal.
We saw an example of that
in the earlier construction pattern.
The one on the right works right.
And the one on the left, "silent error."
It doesn't return an object. It returns nothing.
It returns undefined, which is deeply surprising
and wrong.
You don't get a compile time error.
You don't get a runtime error.
You don't get nothing in the log.
This is really bad.
So how does this happen?
Because the two statements look like they should be equivalent.
So let's zoom in on a little bit.
Look at what's going on.
All right, you remember I told you about semicolon insertion?
How we'll sometimes put semicolons
where they shouldn't go?
This is one of those times,
so it puts a semicolon in there.
So a return statement with no value after it
and no expression after it,
will return undefined in most contexts.
Occasionally, it'll return these.
So but there's a lot of other junk here.
That should cause some sort of syntax error or something.
Give us some sort of warning.
Well, no, because it turns out that curly brace
can mean "start an object literal",
or it could mean a block.
Now it turns out, in this language,
we don't have block scope.
So having an empty block is not useful.
We have one.
The syntax prefers a block to a literal in this notation,
so that's what we get.
Okay, so "ok" doesn't look like a statement.
Well, actually it does. It looks like a statement label.
Well, "false" doesn't look like any kind of a statement.
But, remember, we have those useless expression statements
that we inherited from C.
So we'll evaluate "false" and go, "Yep, that's false.",
and ignore it.
But it doesn't have a semicolon after it.
Well, that's not a problem, because semicolon insertion
comes in, repairs that one.
Now we've got an extra semicolon at the bottom there.
That should trigger an error.
No, 'cause from C we also get the empty statement,
which allows you to have as many semicolons as you want.
So all these things tend to work together to mask errors.
Then, finally, we've got some unreachable code here.
But JavaScript doesn't care.
So there's nothing in the language, in the grammar,
that says there's any problem with unreachable code.
So here's a case where bad style produces a very bad result.
You've got code which you think means that
which means that.
That's one of the worst things
a language can do to you.
Now you might be looking at this
and you might be wondering,
"How did this ever become a standard?"
And you might be wondering,
"Why am I betting my career on this piece of crap?"
[laughter]
Um, getting back to the question about standards,
this shouldn't have become a standard.
There was nobody paying attention
and this stuff went through and JavaScript became
the world's biggest programming language
completely independent of its merits.
Given the process by which all of that happened,
we deserve a language which is far, far worse
than JavaScript.
In fact, given its amazing success despite some of these
obvious shortcomings, I think we got lucky.
There's actually enough goodness, smartness,
built into the language that if you can just
avoid the bad parts, the good parts are really good
and are worthwhile.
So I call that "working with the grain."
I spent a lot of time struggling with this language
trying to figure out how to make it work right,
how to make it do good things.
'Cause all the examples that were published
by Netscape at the time and that you could see
coming out of Dreamweaver,
all told you to do really awful stuff.
And it took a long time to figure out
what this was about.
I remember one day I had an epiphany.
"Wait, this is scheme."
You know, I--
There was no documentation which said how functions worked
and the properties of it.
It wasn't accidental.
Brendan Eich, the designer of the language,
always intended to implement a scheme language.
His bosses at Netscape wouldn't let him do a scheme language
because it was too weird looking.
They told him, "Make it more like Java
or Visual Basic or something."
So he did this to it.
So it's not accidental that the good stuff
is in the language.
He put it there intentionally.
So he very quickly put together a prototype, uh, uh,
in an amazingly short time and presented it to management
and it seemed to work.
And they said, "It seems to work."
He said, "Yeah."
So they shipped it.
[laughter]
Then Microsoft observed it and decided to knock it off,
and they reverse engineered it to amazing fidelity.
They found all the errors that were
in that first implementation and copied them exactly.
[laughter]
And when it went to standardization,
all that stuff got locked into the standard.
So this bit I showed you before,
this amazingly silly bit of silliness,
that's not due to errors and implementations.
It's required behavior by the standard.
In fact, all the browsers implement it
exactly that way.
So when JavaScript was first introduced
late in 1995, it was intentionally
mispositioned by Sun and Netscape.
They decided they needed to join together against Microsoft.
And there was some confusion
about why they needed two languages.
'Cause it was clearly that Java was going to be
the language that was going to rule in the future.
Netscape didn't want to give up on this language,
which was called JavaScript at the time.
And their alliance almost broke down
until Marc Andreessen, perhaps as a joke,
suggested that they call it JavaScript
and that way Sun wouldn't have to hate it.
[man speaking indistinctly]
Crockford: I'm sorry?
man: It was LiveScript.
Crockford: It was LiveScript.
Um...
So, um, I looked at the first version of the language
and like all of you, I said,
"Well, this is incompetent crap.
I'm not gonna waste any time on this."
I had an occasion several years later to take another look.
And between that time and the next,
some goodness had been added to the language
that was missing from the first release.
My company was approached by Turner Broadcasting
to do a website for children based on Cartoon Network.
And we had a chat system that we had
that they wanted to adapt
to this online children's community.
So I went down to Atlanta and learned about the requirements
and it was pretty clear our chat system
wasn't going to be good enough to do this.
And I didn't wanna give the money back
because this was, like, the biggest contract
in the history of the company, and I really wanted to do this.
So I don't know where it came from,
but I got this really silly idea.
Maybe we could do it in the web browser just as it is?
So I wrote up a little prototype and it ran on IE 4,
I think, at the time and on Netscape 4.
And I sent it to Atlanta and they liked it.
You could drag and drop little cartoon guys.
They'd never seen anything like that in a browser before.
And they liked that it wasn't a big installation.
It was just a little thing that ran in their browsers,
so it was something they could ask kids to do.
So that was really good. So I went to my team.
And my team, I had some of the best
Java developers in the world.
We'd been together for a long time.
We had a lot of experience at doing this stuff.
And I said, "Okay, this is how we're going to do it.
We're gonna write the client in the browser in JavaScript."
And they all said, and you may remember,
"That's great. What's plan B?
[laughter]
"In fact, we should start plan B right now
because there's no way this is going to work."
And I said, "No, we're not gonna do plan B.
"We're going to do plan A, and it is going to work.
So who wants to do the JavaScript?"
And everybody took a step backward.
So it was, like, I have to do this
or I'm gonna have to give the money back.
And I really didn't wanna give the money back.
So I had to do JavaScript.
And like everybody else, I started doing it
without learning it and was hating it the whole time.
[mild growl]
And it wasn't until I had the scheme epiphany,
which came late, that I understood what it was about.
And it was like, "Oh, okay. This isn't so bad."
There's actually goodness in it and discovering the goodness--
It's like, "There's JSON in it!"
JSON came about it from my experience
using the language and recognizing,
"Hey, this little bit of a language
could be used for doing data interchange."
And it was great. It was already there.
It was free. And it was well done.
So JSON, just as a consequence
of my recognizing it, has become a world standard.
The JSON story--
In 2001, Chip Morningstar and I were at State Software
and we had an early AJAX platform.
Really amazing stuff.
I think it's still better than what's out there today.
And we used JSON for the data exchange.
And we went to potential customers
and we explained how it worked.
And they said, "Well, where's the XML?"
We said, "Oh, we don't need XML. We're doing this.
It's really so much easier and faster."
They'd go, "Oh, we just committed to XML.
I'm sorry. We can't use it."
Or they'd say, "It's not a standard."
I'd say, "Well, yeah, it's a standard.
It's in JavaScript."
"It's not a standard. We can't use it."
So I declared it's a standard.
So I bought json.org and put it up.
One-pager that described it because it's really simple
and it's all the description it needed.
Few years later, I also wrote an RFC
that described it a little bit more formally.
And it's become a world standard.
Basically, I am a standards body.
[laughter]
It became a standard just on my say-so.
So anyway, getting back to the electric community story.
So we--
That JavaScript program, we finished,
we shipped it, we got paid.
All that stuff is great.
Unfortunately, while I was making the money,
the other half of the company was spending the money.
So by the time it all got done, the board
fired the CEO and the COO and made me CEO again
and I had about two week's cash.
Anyway, when you're going through a bankruptcy,
you get a lotta spare time.
[laughter]
And so I remembered a paper that Vaughan Pratt had written
years ago at the first POPL conference
about top-down operator precedents.
Which was this amazingly clever, elegant, lightweight
way of writing parsers.
And he used it for putting an ALGOL-like syntax onto Lisp.
But it turned out the Lisp community
has never wanted syntax.
But the JavaScript community likes syntax.
And so it occurred to me that I could write
a JavaScript parser in the language, and I did.
And it turned out really well.
And then I had this JavaScript interpreter--
or JavaScript parser, and what do I do with it?
So I turned it into a code quality tool
for JavaScript called JSLint.
And so what JSLint does is it parses your program
and analyzes it for the sorts of weaknesses
that I've been showing you.
Identifies the bad parts.
And if you can get it to stop complaining about your program,
then your program probably just contains good parts
and it's more likely to be a good program.
So it imposes a programming discipline
that makes me much more confident
in being in this very dynamic, very loosely typed environment.
The sort of confidence that strict typing gives you,
JSLint gives me in this silly little language.
And it's free.
If you're writing in JavaScript,
you need to be using JSLint.
So go on the web and get it.
If you're evaluating other people's JavaScript,
it's good at that too.
So, say if you're comparing AJAX libraries,
you don't know which one to use.
Run it through JSLint.
See which one is coded well.
It'll tell you very clearly.
One bit of warning.
JSLint will hurt your feelings.
[laughter]
It'll hurt them really bad. It stings.
From time to time, people write to me and say,
"Hey, here's another thing you could test."
And if it makes sense, I'll put it in
and then I'll run all of my old programs against it.
Then you realize, "Well, I really suck."
You know, even though I wrote it,
even though I know what all the rules are,
it still hurts when I run into this stuff.
And so I can imagine your pain
when you go through this stuff.
I do feel it.
Despite that, I recommend do everything it says,
because it's right.
And even though you've been programming and you've got
a good career and you really know what you're doing,
it's smarter about JavaScript than you are.
It's certainly smarter than I am.
I highly recommend you use JSLint.
One of the things that makes it hurt
is that unlearning is really hard.
I get letters from people all the time saying,
"JSLint said my shit stinks. What's up with that?"
And they always use the words "perfectly fine."
"I did this thing and it was perfectly fine."
Well, I think "perfectly fine" is double equal to "faulty."
[laughter]
And there arguing with me. "Why should I have to fix that?"
I don't care if you fix it.
It's not, you know-- Nothing to do with me.
You're not even paying me for this.
I'm just putting it out there free.
If you want your programs to be good, make 'em good.
But, you know, we get really invested in this stuff.
And ultimately it's because unlearning this stuff--
When you learn something wrong it's really hard
to get it right.
In JavaScript, if you're a professional programmer,
you're coming to the language with baggage
from other languages.
And because it looks like Java but works
completely different than Java, it's really easy
to get stuff wrong unless you're paying attention
to what you're doing.
Or if you're a beginner, you probably started
by reading view-source on crap that ultimately
traces all the way back to Dreamweaver.
And it's awful and that's the way people learn.
And once that stuff gets in your head,
it's really hard to get it out, but you need to do it.
Josh Billings said, "It's not ignorance
"does so much damage; it's knowin'
so derned much that ain't so."
And ain't that the truth?
So maybe the best part about this language is its stability.
There have been no new design errors since 1999.
[laughter]
And this is a consequence of--
That's the last time the language spec was revised
was in 1999.
But I think it's a good idea to, every ten years or so,
revisit the specifications.
So we're about to lose this best part.
We're about to come out with a new edition
which is codenamed ES3.1, which will probably
be labeled Fourth Edition.
There's a weird story you might ask me about later
for why it's called and not JavaScript.
This new edition will contain a lot of corrections.
Both corrections to the specification
and some corrections to the language.
It turns out there are cases where, um,
all the browser makers did something different
than the standard and they all got it right.
So we're recognizing that and making the standard better.
There are also places where we saw
three out of four of the browser makers
were doing one thing and Microsoft was doing another.
We're fixing that now too.
The next version of JScript coming out of Microsoft
will be in much closer alliance to the common language
than everybody else.
So one of the key benefits from this language is that
cross-browser compatibility will be significantly improved.
Now it turns out JavaScript is already, I think,
one of the best languages in the world in terms
of compatibility with multiple implementations.
You know, two JavaScript engines are much more likely
to be compatible at a really deep level
than, say, two C engines.
JavaScript gets knocked pretty hard
about cross-browser compatibility.
But most of those problems are due to the DOM.
The language itself tends to be pretty good.
It's gonna get even better.
We're providing support for object hardening.
So objects right now are maybe too dynamic,
where everything in them is completely malleable
all the time.
So we can now make objects immutable,
where you can lock down individual properties
or lock the whole object down.
This will be particularly good as we start looking
someday towards secure mashups, where you can have
a hardened object which you can give to other code
and know that it cannot be compromised.
We'll also have a new strict mode for reliability.
So there are a lot of things in the language
which are just intolerable.
But the biggest problem with the bad parts
in this language isn't that they are useless.
They actually are occasionally useful.
And so the web has found uses for all
of the really bad parts of the language.
So we were very greatly constrained
in what we could take out.
And we've tried to be respectful for existing code
and tried to minimize the breakage
that the new language will cause.
But there's some stuff in the language
which really has to be fixed.
So we now have an opt-in mode.
You can say "strict mode" and put it in the top
of your program or in the top of your function
and that says, "I don't want the crappy behavior.
I want the rational behavior."
I recommend you not put the strict mode tag
into your program unless you understand what it does
and what it means and that's the language
you want to be writing in.
But I recommend that's the language
that you want to be writing in.
So right now we're waiting on implementations.
The specification's just about done.
Microsoft and Mozilla both committed to public testing.
If the testing goes well, then the standards
should go to the ECMA general assembly in December
and I'm hoping that it will pass.
And then we'll probably see it up here in web browsers
even before that.
If you could hold it to the end.
We're almost there.
Something that's not coming soon
is a competing project called ES4.
That project has been cancelled.
There were some good ideas in that project though
and they've been resurrected in a follow-on
to 3.1 called Harmony.
So far, the project doesn't have any defined goals or rules,
so it's a little vague as to what it's gonna turn out to be.
We'll keep an eye on that.
There's been some real interesting work lately
in secure subsets.
JavaScript is not a secure programming language
but it's not far off from one.
If you correct--get rid of the global object
and make a few other changes--
hold much closer to its scheme nature,
there's the kernel of a secure language in there.
We've seen some experiments like FBJS out of Facebook,
Caja & Cajita from the Google,
and ADsafe, which is my own work.
ADsafe is intended to make advertising safe.
Currently it's not, and we can talk about that another time.
These subsets will be informing the design of a new language
which will ultimately replace JavaScript.
And there's some exploration going on now at ECMA
for such a language.
So to review the good parts, this is maybe
the best part of all.
Your JavaScript application has the potential
to reach an audience of billions.
There is no other programming platform
that has anywhere near that kind of reach.
And, you know, just that, I think,
should be enough to encourage you to wanna
be on this platform.
If you avoid the bad parts, JavaScript works really well.
There's even brilliance in this language.
There should be love in the JavaScript community
for this language and its designer,
'cause there is goodness here.
And it is possible to write good programs in JavaScript.
There are a lotta people who thought it's not possible
to write good programs, so you shouldn't even try.
My message is it is possible and it is necessary
to write good programs.
If you don't wanna write good programs,
I recommend you find another line of work.
Um, then finally, um, here's the commercial plug.
I wrote this cranky little pamphlet
called "JavaScript: The Good Parts."
So if you wanna know more about this silly language,
that's where to go.
So that's it.
That's all I got for you today. Thank you.
[applause]
So how do we do questions here?
Is there a mic or do I repeat or what?
[man speaking indistinctly]
Crockford: Okay, yes?
man: So strict mode in 3.1, does that actually change
behavior or does it just pick things out?
Crockford: Strict mode, does it change behavior
or does it take things out?
It actually changes some behavior.
So one of--
It does take some things out.
Like, you can't have a "with" statement
in strict mode.
So it does take some features out of the language.
It changes the way some features work.
Like, it greatly constrains how eval works
and reduces its ability to do harm to the state.
It also changes some air behavior.
For example, currently in the language,
if you do an assignment to a read-only property
of an object, you get a silent failure.
Which is a bad thing.
In strict mode, you will now get an exception,
which is a better thing.
Any other questions?
man: I've heard you and some other people I know
talk about ideas for projects to fix the DOM problem.
Can you give us a update on what's going on there?
Crockford: Question is what are we doing about the DOM problem?
One bit of difficulty about that is there are two
independent standards bodies that control
two parts of this system.
ECMA controls the programming language
and W3C controls the API.
And these two organizations, as far as I can tell,
do not cooperate with each other.
They don't talk, they don't share plans.
That's a problem.
And so there's much in the DOM--
Fixing the language will not solve
any of our security problems if the DOM is left the way it is
because it is also hopelessly insecure.
So I'm hoping that we can put ECMA and W3C together
and do a more collaborative approach to revising the DOM.
I see work going on on HTML 5 and the web API stuff
and it's really alarming to me.
I think they're going off in very, very bad direction.
I think it's way too complicated.
I don't think it's addressing our real problems.
It just seems more like a standard maker's holiday to me.
So I'm hoping that we can do a reset there,
start over with a better set of goals
that we can go into the future together.
I'm optimistic about it because of what I've seen
in the AJAX libraries.
You know, the DOM model is just really awful.
There was originally the Netscape model,
which was even worse.
Microsoft improved it.
Microsoft gets beaten up a lot for making the DOM so bad.
I think the thing they did wrong
was they stopped too soon.
But it is bad.
But the AJAX libraries are all very thin.
Just, you know, a little bit of code,
you know, generally on the order of 20 to 40k,
which makes it so much better, you know?
So eventually I'd like to take a look
at the lessons that we got from the AJAX libraries,
and then refactor the DOM based on that,
push it down, and that becomes the new API.
Yeah?
man: What about Lambdasoft?
Lambda is good. I like Lambda.
You had lots of praise for it.
But Lambda's more than closures.
How do you spell Lambda in JavaScript?
Crockford: How do you spell Lambda in JavaScript function?
So you don't get everything that you get in scheme.
You know, so we don't have continuations.
We don't have tail recursion optimization.
There's a lot of stuff that's missing.
But the basic notion of helixical scoping is there
and functions as first-class values.
Yes?
man: You mentioned the worst mistake in JavaScript
was the use of global variables for linkage.
What's your preferred way of solving that problem?
Crockford: So I said the worst problem
in JavaScript was its use of global variables for linkage.
How would I solve that?
I'd like to have some...
discovery pattern in which each of the compilation units
is initially completely isolated,
but is given a capability which allows it to introduce itself
to some other capability manager.
So they can make introductions to each other
and form a network.
Uh, uh, yeah?
man: You said that there is no issues with using objects
as though they were hash tables.
Remind me what key you would use [indistinct].
Crockford: Okay, so Waldemar is getting after me about--
JavaScript objects are not strictly hash tables,
or are defective hash tables, I think is maybe more correct.
In that there are some names which will cause collisions.
And, in fact, some of the stuff we came up with in 3.1
is a little odd in the way it's put together
and that was in order to not worsen that problem.
So, yeah, it's not perfect.
Like so much in this language, it's not perfect.
Yes?
man: You were saying that you think that web apps
and HTML 5 is going in the wrong direction.
What things do you think that we're doing wrong?
Is it just that we're not solving the problems,
or is it are we actually adding to them?
Crockford: What do I think is wrong with HTML 5?
man: And the web apps.
Crockford: And the web apps?
I think it's doing too much.
You can look at any individual thing and say,
"Oh, that looks nice."
But there are way too many of those things.
I would like to see a more disciplined approach.
I'd like to see a more minimalist approach.
You know, so if you look at the two proposals
that were competing for the fourth edition,
ES3.1 and ES4.
I preferred ES3.1.
It was less ambitious but it was less likely to cause problems.
And it was moving more toward minimalism.
Which I think is something which is way underrated,
Particularly in standards.
My view of minimalism, particularly after
the JSON standard, is that the less
we have to agree on in order to work together, the better.
And so I would like to look at a way of re-engineering HTML
and all the stuff that goes around it
to be much smaller and work better.
And, you know, I see HTML 5 and the web apps
going in the other direction, which is just
the emperor's old clothes approach,
where you just keep piling more stuff and more stuff
and more stuff. It just gets too big.
It's easy to make things bigger.
It's harder to make things better.
Okay. Yeah?
man: How did it come about that JSON and, uh, ECMAscript
have the same syntax, but almost--but not quite?
Crockford: Yeah, so how'd it come about
that JSON and JavaScript have almost the same syntax?
I think it's just in the two line-ending characters.
Yeah? Yeah.
It's because I missed that line in the standard
when I was putting it together.
When I specified what the whitespace characters were,
carriage return, line feed, tab, and space.
And I missed that--
What-- PS and?
man: And LS?
Crockford: And LS.
Were also recognized as whitespace.
We tried to fix that in the ECMAscript standard
and we couldn't.
So we're stuck with that little bit of difference.
As far as I can tell, nobody's ever used
PS and NLS in this context, so...
[man speaking indistinctly]
Crockford: Yeah, but I've never seen anybody use them.
So it hasn't been a problem yet.
There's a potential security hazard in that
the two systems view it differently.
Particularly when--
But we never identified an exploit that came from that.
And now that there's an explicit JSON parser built in
to JavaScript--that's one of the new good parts, by the way.
That problem goes away completely.
Yes?
man: So the first time I was using JSON,
the first problem I ran into, like, first object
I tried to parse with the JSON parser,
it wouldn't parse and it was because I didn't put quotes
around my property names.
Is there a reason for why that is not allowed?
Crockford: Yeah, so why does JSON require quotes
around the property names?
There are three reasons.
One of the reasons is that I wanted to align it with Python.
In Python, the quotes are required.
Another reason was it makes the grammar of the standard
much easier to specify and I like simplicity.
But the real reason, the true reason,
is that JavaScript has a-- okay, I'll say it--
a stupid reserved word policy.
And there are certain words that you cannot use
in the key position of an object literal.
Many of those names are not even used in the language.
They're reserved unnecessarily
and there's just no reason for it.
And at the time that I put JSON together,
it wasn't like I was riding on JavaScript's coattails,
because nobody was using JavaScript at that time
and everybody hated JavaScript.
So it wasn't like I was basking in JavaScript's glow.
So in order to not have quotes but still use it in JavaScript,
I was going to have to have an appendix of the JSON spec,
which was gonna be at least as big as all the rest of the spec
describing how the reserve words worked.
Basically what it said, "This is something
that's really stupid in JavaScript."
You know, need to point it out.
And at that point, I didn't wanna make JavaScript
look stupider.
So I said, "Okay, we'll just quote the keys and then we don't
have to tell anybody about this shameful thing."
One bit of good news.
We fixed that in the next language.
Reserved words are now allowed in key position
and also in dot position in the language.
So that's better.
But that took a long time.
Uh, one more question?
Yeah? All right, one more.
Yes?
man: Are there any prospects for adding concurrency
to the language?
Crockford: Are there any prospects for adding concurrency
to the language?
It depends on what you mean by "concurrency."
Brendan Eich is pretty adamant and I completely agree with him.
We should not put threads in this language.
I would like to see some sort of messaging model.
I don't know that it belongs in this language.
More likely, it belongs in some layer beside the language.
We would definitely benefit from that.
man: There is--Firefox 3.1 is gonna have support
for APIs that allow you to create
separate threads that can send messages to each other.
Crockford: Yeah, I like that model a lot.
Okay, that's all I got for you today.
Thanks.
[applause]
Souders: That was an amazing talk, Doug.
Thank you very much.