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.
His whole lecture series is great. Required watching for any JavaScript coder: http://yuiblog.com/crockford/
Programming beginner here, What is lambda?
The things I find say anonymous functions, but I don't want to accept that in case it's an over-simplification.