JavaScript语言精粹(JavaScript.The.Good.Parts)


JavaScript: The Good Parts Other resources from O’Reilly Related titles High Performance Web Sites JavaScript and DHTML Cookbook™ JavaScript: The Definitive Guide Learning JavaScript oreilly.com oreilly.com is more than a complete catalog of O’Reilly books. You’ll also find links to news, events, articles, weblogs, sample chapters, and code examples. oreillynet.com is the essential portal for developers interested in open and emerging technologies, including new platforms, pro- gramming languages, and operating systems. Conferences O’Reilly brings diverse innovators together to nurture the ideas that spark revolutionary industries. We specialize in document- ing the latest tools and systems, translating the innovator’s knowledge into useful skills for those in the trenches. Visit conferences.oreilly.com for our upcoming events. Safari Bookshelf (safari.oreilly.com) is the premier online refer- ence library for programmers and IT professionals. Conduct searches across more than 1,000 books. Subscribers can zero in on answers to time-critical questions in a matter of seconds. Read the books on your Bookshelf from cover to cover or sim- ply flip to the page you need. Try it today for free. JavaScript: The Good Parts Douglas Crockford Beijing • Cambridge • Farnham • Köln • Sebastopol • Tokyo JavaScript: The Good Parts by Douglas Crockford Copyright © 2008 Yahoo! Inc. All rights reserved. Printed in the United States of America. Published by O’Reilly Media, Inc., 1005 Gravenstein Highway North, Sebastopol, CA 95472. O’Reilly books may be purchased for educational, business, or sales promotional use. Online editions are also available for most titles (safari.oreilly.com). For more information, contact our corporate/institutional sales department: (800) 998-9938 or corporate@oreilly.com. Editor: Simon St.Laurent Production Editor: Sumita Mukherji Copyeditor: Genevieve d’Entremont Proofreader: Sumita Mukherji Indexer: Julie Hawks Cover Designer: Karen Montgomery Interior Designer: David Futato Illustrator: Robert Romano Printing History: May 2008: First Edition. Nutshell Handbook, the Nutshell Handbook logo, and the O’Reilly logo are registered trademarks of O’Reilly Media, Inc. JavaScript: The Good Parts, the image of a Plain Tiger butterfly, and related trade dress are trademarks of O’Reilly Media, Inc. Java™ is a trademark of Sun Microsystems, Inc. Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where those designations appear in this book, and O’Reilly Media, Inc. was aware of a trademark claim, the designations have been printed in caps or initial caps. While every precaution has been taken in the preparation of this book, the publisher and author assume no responsibility for errors or omissions, or for damages resulting from the use of the information contained herein. This book uses RepKover™, a durable and flexible lay-flat binding. ISBN: 978-0-596-51774-8 [M] 42.5# [11/10] For the Lads: Clement, Philbert, Seymore, Stern, and, lest we forget, C. Twildo. vii Table of Contents Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xi 1. Good Parts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 Why JavaScript? 2 Analyzing JavaScript 3 A Simple Testing Ground 4 2. Grammar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 Whitespace 5 Names 6 Numbers 7 Strings 8 Statements 10 Expressions 15 Literals 17 Functions 19 3. Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 Object Literals 20 Retrieval 21 Update 22 Reference 22 Prototype 22 Reflection 23 Enumeration 24 Delete 24 Global Abatement 25 viii | Table of Contents 4. Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 Function Objects 26 Function Literal 27 Invocation 27 Arguments 31 Return 31 Exceptions 32 Augmenting Types 32 Recursion 34 Scope 36 Closure 37 Callbacks 40 Module 40 Cascade 42 Curry 43 Memoization 44 5. Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 Pseudoclassical 47 Object Specifiers 50 Prototypal 50 Functional 52 Parts 55 6. Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 Array Literals 58 Length 59 Delete 60 Enumeration 60 Confusion 61 Methods 62 Dimensions 63 7. Regular Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 An Example 66 Construction 70 Elements 72 Table of Contents | ix 8. Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78 9. Style . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 10. Beautiful Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 Appendix A. Awful Parts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 Appendix B. Bad Parts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109 Appendix C. JSLint . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 Appendix D. Syntax Diagrams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 Appendix E. JSON . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136 Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 xi Preface1 If we offend, it is with our good will That you should think, we come not to offend, But with good will. To show our simple skill, That is the true beginning of our end. —William Shakespeare, A Midsummer Night’s Dream This is a book about the JavaScript programming language. It is intended for pro- grammers who, by happenstance or curiosity, are venturing into JavaScript for the first time. It is also intended for programmers who have been working with JavaScript at a novice level and are now ready for a more sophisticated relationship with the lan- guage. JavaScript is a surprisingly powerful language. Its unconventionality presents some challenges, but being a small language, it is easily mastered. My goal here is to help youto learn to think in JavaScript. I will show youthe com- ponents of the language and start you on the process of discovering the ways those components can be put together. This is not a reference book. It is not exhaustive about the language and its quirks. It doesn’t contain everything you’ll ever need to know. That stuff you can easily find online. Instead, this book just contains the things that are really important. This is not a book for beginners. Someday I hope to write a JavaScript: The First Parts book, but this is not that book. This is not a book about Ajax or web program- ming. The focus is exclusively on JavaScript, which is just one of the languages the web developer must master. This is not a book for dummies. This book is small, but it is dense. There is a lot of material packed into it. Don’t be discouraged if it takes multiple readings to get it. Your efforts will be rewarded. xii | Preface Conventions Used in This Book The following typographical conventions are used in this book: Italic Indicates new terms, URLs, filenames, and file extensions. Constant width Indicates computer coding in a broad sense. This includes commands, options, variables, attributes, keys, requests, functions, methods, types, classes, modules, properties, parameters, values, objects, events, event handlers, XML and XHTML tags, macros, and keywords. Constant width bold Indicates commands or other text that should be typed literally by the user. Using Code Examples This book is here to help youget yourjob done. In general, youmay usethe code in this book in your programs and documentation. You do not need to contact us for permission. For example, writing a program that uses several chunks of code from this book does not require permission. Selling or distributing a CD-ROM of exam- ples from O’Reilly books does require permission. Answering a question by citing this book and quoting example code does not require permission. Incorporating a significant amount of example code from this book into your product’s documenta- tion does require permission. We appreciate, but do not require, attribution. An attribution usually includes the title, author, publisher, and ISBN. For example: “JavaScript: The Good Parts by Dou- glas Crockford. Copyright 2008 Yahoo! Inc., 978-0-596-51774-8.” If you feel your use of code examples falls outside fair use or the permission given here, feel free to contact us at permissions@oreilly.com. Safari® Books Online When yousee a Safari® Books Online icon on the cover of your favorite technology book, that means the book is available online through the O’Reilly Network Safari Bookshelf. Safari offers a solution that’s better than e-books. It’s a virtual library that lets you easily search thousands of top tech books, cut and paste code samples, download chapters, and find quick answers when you need the most accurate, current informa- tion. Try it for free at http://safari.oreilly.com. Preface | xiii How to Contact Us Please address comments and questions concerning this book to the publisher: O’Reilly Media, Inc. 1005 Gravenstein Highway North Sebastopol, CA 95472 800-998-9938 (in the United States or Canada) 707-829-0515 (international or local) 707-829-0104 (fax) We have a web page for this book, where we list errata, examples, and any addi- tional information. You can access this page at: http://www.oreilly.com/catalog/9780596517748/ To comment or ask technical questions about this book, send email to: bookquestions@oreilly.com For more information about our books, conferences, Resource Centers, and the O’Reilly Network, see our web site at: http://www.oreilly.com/ Acknowledgments I want to thank the reviewers who pointed out my many egregious errors. There are few things better in life than having really smart people point out your blunders. It is even better when they do it before you go public. Thank you, Steve Souders, Bill Scott, Julien Lecomte, Stoyan Stefanov, Eric Miraglia, and Elliotte Rusty Harold. I want to thank the people I worked with at Electric Communities and State Soft- ware who helped me discover that deep down there was goodness in this language, especially Chip Morningstar, Randy Farmer, John La, Mark Miller, Scott Shattuck, and Bill Edney. I want to thank Yahoo! Inc. for giving me time to work on this project and for being such a great place to work, and thanks to all members of the Ajax Strike Force, past and present. I also want to thank O’Reilly Media, Inc., particularly Mary Treseler, Simon St.Laurent, and Sumita Mukherji for making things go so smoothly. Special thanks to Professor Lisa Drake for all those things she does. And I want to thank the guys in ECMA TC39 who are struggling to make ECMAScript a better language. Finally, thanks to Brendan Eich, the world’s most misunderstood programming lan- guage designer, without whom this book would not have been necessary. 1 Chapter 1 CHAPTER 1 Good Parts1 …setting the attractions of my good parts aside I have no other charms. —William Shakespeare, The Merry Wives of Windsor When I was a young journeyman programmer, I would learn about every feature of the languages I was using, and I would attempt to use all of those features when I wrote. I suppose it was a way of showing off, and I suppose it worked because I was the guy you went to if you wanted to know how to use a particular feature. Eventually I figured out that some of those features were more trouble than they were worth. Some of them were poorly specified, and so were more likely to cause portability problems. Some resulted in code that was difficult to read or modify. Some induced me to write in a manner that was too tricky and error-prone. And some of those features were design errors. Sometimes language designers make mistakes. Most programming languages contain good parts and bad parts. I discovered that I could be a better programmer by using only the good parts and avoiding the bad parts. After all, how can you build something good out of bad parts? It is rarely possible for standards committees to remove imperfections from a lan- guage because doing so would cause the breakage of all of the bad programs that depend on those bad parts. They are usually powerless to do anything except heap more features on top of the existing pile of imperfections. And the new features do not always interact harmoniously, thus producing more bad parts. But you have the power to define your own subset. You can write better programs by relying exclusively on the good parts. JavaScript is a language with more than its share of bad parts. It went from non- existence to global adoption in an alarmingly short period of time. It never had an interval in the lab when it could be tried out and polished. It went straight into Netscape Navigator 2 just as it was, and it was very rough. When Java™ applets failed, JavaScript became the “Language of the Web” by default. JavaScript’s popu- larity is almost completely independent of its qualities as a programming language. 2 | Chapter 1: Good Parts Fortunately, JavaScript has some extraordinarily good parts. In JavaScript, there is a beautiful, elegant, highly expressive language that is buried under a steaming pile of good intentions and blunders. The best nature of JavaScript is so effectively hidden that for many years the prevailing opinion of JavaScript was that it was an unsightly, incompetent toy. My intention here is to expose the goodness in JavaScript, an out- standing, dynamic programming language. JavaScript is a block of marble, and I chip away the features that are not beautiful until the language’s true nature reveals itself. I believe that the elegant subset I carved out is vastly superior to the language as a whole, being more reliable, readable, and maintainable. This book will not attempt to fully describe the language. Instead, it will focus on the good parts with occasional warnings to avoid the bad. The subset that will be described here can be used to construct reliable, readable programs small and large. By focusing on just the good parts, we can reduce learning time, increase robustness, and save some trees. Perhaps the greatest benefit of studying the good parts is that you can avoid the need to unlearn the bad parts. Unlearning bad patterns is very difficult. It is a painful task that most of us face with extreme reluctance. Sometimes languages are subsetted to make them work better for students. But in this case, I am subsetting JavaScript to make it work better for professionals. Why JavaScript? JavaScript is an important language because it is the language of the web browser. Its association with the browser makes it one of the most popular programming lan- guages in the world. At the same time, it is one of the most despised programming languages in the world. The API of the browser, the Document Object Model (DOM) is quite awful, and JavaScript is unfairly blamed. The DOM would be pain- ful to work with in any language. The DOM is poorly specified and inconsistently implemented. This book touches only very lightly on the DOM. I think writing a Good Parts book about the DOM would be extremely challenging. JavaScript is most despised because it isn’t some other language. If youare good in some other language and youhave to program in an environment that only supports JavaScript, then youare forced to useJavaScript, and that is annoying. Most people in that situation don’t even bother to learn JavaScript first, and then they are sur- prised when JavaScript turns out to have significant differences from the some other language they would rather be using, and that those differences matter. The amazing thing about JavaScript is that it is possible to get work done with it without knowing much about the language, or even knowing much about program- ming. It is a language with enormous expressive power. It is even better when you know what you’re doing. Programming is difficult business. It should never be undertaken in ignorance. Analyzing JavaScript | 3 Analyzing JavaScript JavaScript is built on some very good ideas and a few very bad ones. The very good ideas include functions, loose typing, dynamic objects, and an expres- sive object literal notation. The bad ideas include a programming model based on global variables. JavaScript’s functions are first class objects with (mostly) lexical scoping. JavaScript is the first lambda language to go mainstream. Deep down, JavaScript has more in common with Lisp and Scheme than with Java. It is Lisp in C’s clothing. This makes JavaScript a remarkably powerful language. The fashion in most programming languages today demands strong typing. The the- ory is that strong typing allows a compiler to detect a large class of errors at compile time. The sooner we can detect and repair errors, the less they cost us. JavaScript is a loosely typed language, so JavaScript compilers are unable to detect type errors. This can be alarming to people who are coming to JavaScript from strongly typed lan- guages. But it turns out that strong typing does not eliminate the need for careful testing. And I have found in my work that the sorts of errors that strong type check- ing finds are not the errors I worry about. On the other hand, I find loose typing to be liberating. I don’t need to form complex class hierarchies. And I never have to cast or wrestle with the type system to get the behavior that I want. JavaScript has a very powerful object literal notation. Objects can be created simply by listing their components. This notation was the inspiration for JSON, the popu- lar data interchange format. (There will be more about JSON in Appendix E.) A controversial feature in JavaScript is prototypal inheritance. JavaScript has a class- free object system in which objects inherit properties directly from other objects. This is really powerful, but it is unfamiliar to classically trained programmers. If you attempt to apply classical design patterns directly to JavaScript, you will be frustrated. But if you learn to work with JavaScript’s prototypal nature, your efforts will be rewarded. JavaScript is much maligned for its choice of key ideas. For the most part, though, those choices were good, if unusual. But there was one choice that was particularly bad: JavaScript depends on global variables for linkage. All of the top-level variables of all compilation units are tossed together in a common namespace called the global object. This is a bad thing because global variables are evil, and in JavaScript they are fundamental. Fortunately, as we will see, JavaScript also gives us the tools to miti- gate this problem. In a few cases, we can’t ignore the bad parts. There are some unavoidable awful parts, which will be called out as they occur. They will also be summarized in Appendix A. But we will succeed in avoiding most of the bad parts in this book, summarizing much of what was left out in Appendix B. If you want to learn more about the bad parts and how to use them badly, consult any other JavaScript book. 4 | Chapter 1: Good Parts The standard that defines JavaScript (aka JScript) is the third edition of The ECMAScript Programming Language, which is available from http://www.ecma- international.org/publications/files/ecma-st/ECMA-262.pdf. The language described in this book is a proper subset of ECMAScript. This book does not describe the whole language because it leaves out the bad parts. The treatment here is not exhaustive. It avoids the edge cases. You should, too. There is danger and misery at the edges. Appendix C describes a programming tool called JSLint, a JavaScript parser that can analyze a JavaScript program and report on the bad parts that it contains. JSLint pro- vides a degree of rigor that is generally lacking in JavaScript development. It can give you confidence that your programs contain only the good parts. JavaScript is a language of many contrasts. It contains many errors and sharp edges, so you might wonder, “Why should I use JavaScript?” There are two answers. The first is that youdon’t have a choice. The Web has become an important platform for application development, and JavaScript is the only language that is found in all browsers. It is unfortunate that Java failed in that environment; if it hadn’t, there could be a choice for people desiring a strongly typed classical language. But Java did fail and JavaScript is flourishing, so there is evidence that JavaScript did something right. The other answer is that, despite its deficiencies, JavaScript is really good. It is light- weight and expressive. And once youget the hang of it, functionalprogramming is a lot of fun. But in order to use the language well, you must be well informed about its limita- tions. I will pound on those with some brutality. Don’t let that discourage you. The good parts are good enough to compensate for the bad parts. A Simple Testing Ground If youhave a web browser and any text editor, youhave everything youneed to run JavaScript programs. First, make an HTML file with a name like program.html:
Then, make a file in the same directory with a name like program.js: document.writeln('Hello, world!'); Next, open your HTML file in your browser to see the result. Throughout the book, a method method is used to define new methods. This is its definition: Function.prototype.method = function (name, func) { this.prototype[name] = func; return this; }; It will be explained in Chapter 4. 5 Chapter 2 CHAPTER 2 Grammar2 I know it well: I read it in the grammar long ago. —William Shakespeare, The Tragedy of Titus Andronicus This chapter introduces the grammar of the good parts of JavaScript, presenting a quick overview of how the language is structured. We will represent the grammar with railroad diagrams. The rules for interpreting these diagrams are simple: • You start on the left edge and follow the tracks to the right edge. • As you go, you will encounter literals in ovals, and rules or descriptions in rectangles. • Any sequence that can be made by following the tracks is legal. • Any sequence that cannot be made by following the tracks is not legal. • Railroad diagrams with one bar at each end allow whitespace to be inserted between any pair of tokens. Railroad diagrams with two bars at each end do not. The grammar of the good parts presented in this chapter is significantly simpler than the grammar of the whole language. Whitespace Whitespace can take the form of formatting characters or comments. Whitespace is usually insignificant, but it is occasionally necessary to use whitespace to separate sequences of characters that would otherwise be combined into a single token. For example, in: var that = this; the space between var and that cannot be removed, but the other spaces can be removed. 6 | Chapter 2: Grammar JavaScript offers two forms of comments, block comments formed with /* */ and line-ending comments starting with //. Comments should be used liberally to improve the readability of your programs. Take care that the comments always accu- rately describe the code. Obsolete comments are worse than no comments. The /* */ form of block comments came from a language called PL/I. PL/I chose those strange pairs as the symbols for comments because they were unlikely to occur in that language’s programs, except perhaps in string literals. In JavaScript, those pairs can also occur in regular expression literals, so block comments are not safe for commenting out blocks of code. For example: /* var rm_a = /a*/.match(s); */ causes a syntax error. So, it is recommended that /* */ comments be avoided and // comments be used instead. In this book, // will be used exclusively. Names A name is a letter optionally followed by one or more letters, digits, or underbars. A name cannot be one of these reserved words: abstract boolean break byte case catch char class const continue debugger default delete do double space tab line end any character except line end any character except * and / // * / */ whitespace Numbers | 7 else enum export extends false final finally float for function goto if implements import in instanceof int interface long native new null package private protected public return short static super switch synchronized this throw throws transient true try typeof var volatile void while with Most of the reserved words in this list are not used in the language. The list does not include some words that should have been reserved but were not, such as undefined, NaN, and Infinity. It is not permitted to name a variable or parameter with a reserved word. Worse, it is not permitted to use a reserved word as the name of an object property in an object literal or following a dot in a refinement. Names are used for statements, variables, parameters, property names, operators, and labels. Numbers JavaScript has a single number type. Internally, it is represented as 64-bit floating point, the same as Java’s double. Unlike most other programming languages, there is no separate integer type, so 1 and 1.0 are the same value. This is a significant conve- nience because problems of overflow in short integers are completely avoided, and all you need to know about a number is that it is a number. A large class of numeric type errors is avoided. letter name digit _ integer fraction exponent number literal 8 | Chapter 2: Grammar If a number literal has an exponent part, then the value of the literal is computed by multiplying the part before the e by 10 raised to the power of the part after the e.So 100 and 1e2 are the same number. Negative numbers can be formed by using the – prefix operator. The value NaN is a number value that is the result of an operation that cannot pro- duce a normal result. NaN is not equal to any value, including itself. You can detect NaN with the isNaN(number) function. The value Infinity represents all values greater than 1.79769313486231570e+308. Numbers have methods (see Chapter 8). JavaScript has a Math object that contains a set of methods that act on numbers. For example, the Math.floor(number) method can be used to convert a number into an integer. Strings A string literal can be wrapped in single quotes or double quotes. It can contain zero or more characters. The \ (backslash) is the escape character. JavaScript was built at a time when Unicode was a 16-bit character set, so all characters in JavaScript are 16 bits wide. JavaScript does not have a character type. To represent a character, make a string with just one character in it. any digit except 0 digit integer 0 digit fraction . exponent e digit+ E- Strings | 9 The escape sequences allow for inserting characters into strings that are not nor- mally permitted, such as backslashes, quotes, and control characters. The \u conven- tion allows for specifying character code points numerically. "A" === "\u0041" Strings have a length property. For example, "seven".length is 5. Strings are immutable. Once it is made, a string can never be changed. But it is easy to make a new string by concatenating other strings together with the + operator. any Unicode character except " and \ and control character string literal "" escaped character ''any Unicode character except ' and \ and control character escaped character escaped character \ " double quote ' single quote \ backslash / slash b backspace f formfeed n new line r carriage return t tab u 4 hexadecimal digits 10 | Chapter 2: Grammar Two strings containing exactly the same characters in the same order are considered to be the same string. So: 'c' + 'a' + 't' === 'cat' is true. Strings have methods (see Chapter 8): 'cat'.toUpperCase( ) === 'CAT' Statements A compilation unit contains a set of executable statements. In web browsers, each tags and event handlers. It also inspects the HTML content, looking for problems that are known to interfere with JavaScript: • All tag names must be in lowercase. • All tags that can take a close tag (such as

) must have a close tag. • All tags are correctly nested. • The entity < must be used for literal <. JSLint is less anal than the sycophantic conformity demanded by XHTML, but more strict than the popular browsers. JSLint also checks for the occurrence of = less or equal <= > greater < less equal === not equal !== && logical and any digit except 0 digit integer 0 invocation expression )( , literal number literal string literal object literal array literal function regexp literal 130 | Appendix D: Syntax Diagrams letter name digit _ integer fraction exponent number literal object literal name expression string :{} , name parameters , )( prefix operator typeof type of + - ! to number negate logical not Syntax Diagrams | 131 refinement name. []expression regexp choice regexp sequence | regexp class []any Unicode character except / and \ and [ and ] and ^ and - and control character ^ - regexp class escape regexp class escape any special character f \ formfeed n newline r carriage return t tab u 4 hexadecimal digits not D S W d digit s whitespace w word character literal b backspace 132 | Appendix D: Syntax Diagrams regexp escape any special character f \ formfeed n newline r carriage return t tab u 4 hexadecimal digits B not D S W b word boundary d digit s whitespace w word character literal back reference integer regexp factor any Unicode character except / and \ and [ and ] and ( and ) and { and } and ? and + and * and | and control character regexp escape regexp class regexp group regexp choice regexp group ( capturing ?:non-capturing = positive lookahead ! negative lookahead ) Syntax Diagrams | 133 regexp choice//g im regexp literal regexp quantifier ? * + { , } ? integer integer regexp sequence regexp factor regexp quantifier return statement return expression ; statements expression statement ; do statement for statement while statement switch statement if statement try statement disruptive statement name label : 134 | Appendix D: Syntax Diagrams any Unicode character except " and \ and control character string literal "" escaped character ''any Unicode character except ' and \ and control character escaped character switch statement switch )expression( default { case clause disruptive statement statements } : throw statement throw expression ; try statement try ( namecatchblock ) block variable var statements name expression ; , =var while statement while block( expression ) Syntax Diagrams | 135 space tab line end any character except line end any character except * and / // * / */ whitespace 136 Appendix EAPPENDIX E JSON 5 Farewell: the leisure and the fearful time Cuts off the ceremonious vows of love And ample interchange of sweet discourse, Which so long sunder’d friends should dwell upon: God give us leisure for these rites of love! Once more, adieu: be valiant, and speed well! —William Shakespeare, The Tragedy of Richard the Third JavaScript Object Notation (JSON) is a lightweight data interchange format. It is based on JavaScript’s object literal notation, one of JavaScript’s best parts. Even though it is a subset of JavaScript, it is language independent. It can be used to exchange data between programs written in all modern programming languages. It is a text format, so it is readable by humans and machines. It is easy to implement and easy to use. There is a lot of material about JSON at http://www.JSON.org/. JSON Syntax JSON has six kinds of values: objects, arrays, strings, numbers, booleans (true and false), and the special value null. Whitespace (spaces, tabs, carriage returns, and newline characters) may be inserted before or after any value. This can make JSON texts easier for humans to read. Whitespace may be omitted to reduce transmission or storage costs. A JSON object is an unordered container of name/value pairs. A name can be any string. A value can be any JSON value, including arrays and objects. JSON objects can be nested to any depth, but generally it is most effective to keep them relatively flat. Most languages have a feature that maps easily to JSON objects, such as an object, struct, record, dictionary, hash table, property list, or associative array. The JSON array is an ordered sequence of values. A value can be any JSON value, including arrays and objects. Most languages have a feature that maps easily onto JSON arrays, such as an array, vector, list, or sequence. JSON Syntax | 137 A JSON string is wrapped in double quotes. The \ character is used for escapement. JSON allows the / character to be escaped so that JSON can be embedded in HTML tag. JSON allows <\/, which produces the same result but does not confuse HTML. JSON numbers are like JavaScript numbers. A leading zero is not allowed on inte- gers because some languages use that to indicate the octal. That kind of radix confu- sion is not desirable in a data interchange format. A number can be an integer, real, or scientific. That’s it. That is all of JSON. JSON’s design goals were to be minimal, portable, tex- tual, and a subset of JavaScript. The less we need to agree on in order to interoperate, the more easily we can interoperate. JSON value true false null JSON object JSON array JSON string JSON number JSON object JSON string JSON value{}: , JSON array JSON value[] , 138 | Appendix E: JSON [ { "first": "Jerome", "middle": "Lester", "last": "Howard", "nick-name": "Curly", "born": 1903, "died": 1952, "quote": "nyuk-nyuk-nyuk!" JSON string "" \ " quotation mark \ reverse solidus / solidus b backspace f formfeed n newline r carriage return t horizontal tab u 4 hexadecimal digits any Unicode character except " or \ or control character JSON number integer fraction exponent digit 1-9 digit digit digit - 0 .Ee +- Using JSON Securely | 139 }, { "first": "Harry", "middle": "Moses", "last": "Howard", "nick-name": "Moe", "born": 1897, "died": 1975, "quote": "Why, you!" }, { "first": "Louis", "last": "Feinberg", "nick-name": "Larry", "born": 1902, "died": 1975, "quote": "I'm sorry. Moe, it was an accident!" } ] Using JSON Securely JSON is particularly easy to use in web applications because JSON is JavaScript. A JSON text can be turned into a useful data structure with the eval function: var myData = eval('(' + myJSONText + ')'); (The concatenation of the parentheses around the JSON text is a workaround for an ambiguity in JavaScript’s grammar.) The eval function has horrendous security problems, however. Is it safe to use eval to parse a JSON text? Currently, the best technique for obtaining data from a server in a web browser is through XMLHttpRequest. XMLHttpRequest can obtain data only from the same server that produced the HTML. evaling text from that server is no less secure than the original HTML. But, that assumes the server is malicious. What if the server is simply incompetent? An incompetent server might not do the JSON encoding correctly. If it builds JSON texts by slapping together some strings rather than using a proper JSON encoder, then it could unintentionally send dangerous material. If it acts as a proxy and sim- ply passes JSON text through without determining whether it is well formed, then it could send dangerous material again. The danger can be avoided by using the JSON.parse method instead of eval (see http:// www.JSON.org/json2.js). JSON.parse will throw an exception if the text contains any- thing dangerous. It is recommended that you always use JSON.parse instead of eval to defend against server incompetence. It is also good practice for the day when the browser provides safe data access to other servers. 140 | Appendix E: JSON There is another danger in the interaction between external data and innerHTML.A common Ajax pattern is for the server to send an HTML text fragment that gets assigned to the innerHTML property of an HTML element. This is a very bad practice. If the HTML text contains a