Thư viện tri thức trực tuyến
Kho tài liệu với 50,000+ tài liệu học thuật
© 2023 Siêu thị PDF - Kho tài liệu học thuật hàng đầu Việt Nam

High Performance JavaScript docx
Nội dung xem thử
Mô tả chi tiết
High Performance JavaScript
High Performance JavaScript
Nicholas C. Zakas
Beijing Cambridge Farnham Köln Sebastopol Taipei Tokyo
High Performance JavaScript
by Nicholas C. Zakas
Copyright © 2010 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 (http://my.safaribooksonline.com). For more information, contact our
corporate/institutional sales department: (800) 998-9938 or [email protected].
Editor: Mary E. Treseler
Production Editor: Adam Zaremba
Copyeditor: Genevieve d’Entremont
Proofreader: Adam Zaremba
Indexer: Fred Brown
Cover Designer: Karen Montgomery
Interior Designer: David Futato
Illustrator: Robert Romano
Printing History:
March 2010: First Edition.
Nutshell Handbook, the Nutshell Handbook logo, and the O’Reilly logo are registered trademarks of
O’Reilly Media, Inc. High Performance JavaScript, the image of a short-eared owl, and related trade dress
are trademarks of O’Reilly Media, 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.
TM
This book uses RepKover™, a durable and flexible lay-flat binding.
ISBN: 978-0-596-80279-0
[M]
1268245906
This book is dedicated to my family, Mom, Dad,
and Greg, whose love and support have kept me
going through the years.
Table of Contents
Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xi
1. Loading and Execution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Script Positioning 2
Grouping Scripts 4
Nonblocking Scripts 5
Deferred Scripts 5
Dynamic Script Elements 6
XMLHttpRequest Script Injection 9
Recommended Nonblocking Pattern 10
Summary 14
2. Data Access . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
Managing Scope 16
Scope Chains and Identifier Resolution 16
Identifier Resolution Performance 19
Scope Chain Augmentation 21
Dynamic Scopes 24
Closures, Scope, and Memory 24
Object Members 27
Prototypes 27
Prototype Chains 29
Nested Members 30
Caching Object Member Values 31
Summary 33
3. DOM Scripting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
DOM in the Browser World 35
Inherently Slow 36
DOM Access and Modification 36
innerHTML Versus DOM methods 37
vii
Cloning Nodes 41
HTML Collections 42
Walking the DOM 46
Repaints and Reflows 50
When Does a Reflow Happen? 51
Queuing and Flushing Render Tree Changes 51
Minimizing Repaints and Reflows 52
Caching Layout Information 56
Take Elements Out of the Flow for Animations 56
IE and :hover 57
Event Delegation 57
Summary 59
4. Algorithms and Flow Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
Loops 61
Types of Loops 61
Loop Performance 63
Function-Based Iteration 67
Conditionals 68
if-else Versus switch 68
Optimizing if-else 70
Lookup Tables 72
Recursion 73
Call Stack Limits 74
Recursion Patterns 75
Iteration 76
Memoization 77
Summary 79
5. Strings and Regular Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
String Concatenation 81
Plus (+) and Plus-Equals (+=) Operators 82
Array Joining 84
String.prototype.concat 86
Regular Expression Optimization 87
How Regular Expressions Work 88
Understanding Backtracking 89
Runaway Backtracking 91
A Note on Benchmarking 96
More Ways to Improve Regular Expression Efficiency 96
When Not to Use Regular Expressions 99
String Trimming 99
Trimming with Regular Expressions 99
viii | Table of Contents
Trimming Without Regular Expressions 102
A Hybrid Solution 103
Summary 104
6. Responsive Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
The Browser UI Thread 107
Browser Limits 109
How Long Is Too Long? 110
Yielding with Timers 111
Timer Basics 112
Timer Precision 114
Array Processing with Timers 114
Splitting Up Tasks 116
Timed Code 118
Timers and Performance 119
Web Workers 120
Worker Environment 120
Worker Communication 121
Loading External Files 122
Practical Uses 122
Summary 124
7. Ajax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
Data Transmission 125
Requesting Data 125
Sending Data 131
Data Formats 134
XML 134
JSON 137
HTML 141
Custom Formatting 142
Data Format Conclusions 144
Ajax Performance Guidelines 145
Cache Data 145
Know the Limitations of Your Ajax Library 148
Summary 149
8. Programming Practices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
Avoid Double Evaluation 151
Use Object/Array Literals 153
Don’t Repeat Work 154
Lazy Loading 154
Conditional Advance Loading 156
Table of Contents | ix
Use the Fast Parts 156
Bitwise Operators 156
Native Methods 159
Summary 161
9. Building and Deploying High-Performance JavaScript Applications . . . . . . . . . . . 163
Apache Ant 163
Combining JavaScript Files 165
Preprocessing JavaScript Files 166
JavaScript Minification 168
Buildtime Versus Runtime Build Processes 170
JavaScript Compression 170
Caching JavaScript Files 171
Working Around Caching Issues 172
Using a Content Delivery Network 173
Deploying JavaScript Resources 173
Agile JavaScript Build Process 174
Summary 175
10. Tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177
JavaScript Profiling 178
YUI Profiler 179
Anonymous Functions 182
Firebug 183
Console Panel Profiler 183
Console API 184
Net Panel 185
Internet Explorer Developer Tools 186
Safari Web Inspector 188
Profiles Panel 189
Resources Panel 191
Chrome Developer Tools 192
Script Blocking 193
Page Speed 194
Fiddler 196
YSlow 198
dynaTrace Ajax Edition 199
Summary 202
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203
x | Table of Contents
Preface
When JavaScript was first introduced as part of Netscape Navigator in 1996, performance wasn’t that important. The Internet was in its infancy and it was, in all ways, slow.
From dial-up connections to underpowered home computers, surfing the Web was
more often a lesson in patience than anything else. Users expected to wait for web pages
to load, and when the page successfully loaded, it was a cause for celebration.
JavaScript’s original goal was to improve the user experience of web pages. Instead of
going back to the server for simple tasks such as form validation, JavaScript allowed
embedding of this functionality directly in the page. Doing so saved a rather long trip
back to the server. Imagine the frustration of filling out a long form, submitting it, and
then waiting 30–60 seconds just to get a message back indicating that you had filled in
a single field incorrectly. JavaScript can rightfully be credited with saving early Internet
users a lot of time.
The Internet Evolves
Over the decade that followed, computers and the Internet continued to evolve. To
start, both got much faster. The rapid speed-up of microprocessors, the availability of
cheap memory, and the appearance of fiber optic connections pushed the Internet into
a new age. With high-speed connections more available than ever, web pages started
becoming heavier, embedding more information and multimedia. The Web had
changed from a fairly bland landscape of interlinked documents into one filled with
different designs and interfaces. Everything changed, that is, except JavaScript.
What previously was used to save server roundtrips started to become more ubiquitous.
Where there were once dozens of lines of JavaScript code were now hundreds, and
eventually thousands. The introduction of Internet Explorer 4 and dynamic HTML
(the ability to change aspects of the page without a reload) ensured that the amount of
JavaScript on pages would only increase over time.
The last major step in the evolution of browsers was the introduction of the Document
Object Model (DOM), a unified approach to dynamic HTML that was adopted by
Internet Explorer 5, Netscape 6, and Opera. This was closely followed by the
xi
standardization of JavaScript into ECMA-262, third edition. With all browsers supporting the DOM and (more or less) the same version of JavaScript, a web application
platform was born. Despite this huge leap forward, with a common API against which
to write JavaScript, the JavaScript engines in charge of executing that code remained
mostly unchanged.
Why Optimization Is Necessary
The JavaScript engines that supported web pages with a few dozen lines of JavaScript
in 1996 are the same ones running web applications with thousands of lines of JavaScript today. In many ways, the browsers fell behind in their management of the language and in doing the groundwork so that JavaScript could succeed at a large scale.
This became evident with Internet Explorer 6, which was heralded for its stability and
speed when it was first released but later reviled as a horrible web application platform
because of its bugs and slowness.
In reality, IE 6 hadn’t gotten any slower; it was just being asked to do more than it had
previously. The types of early web applications being created when IE 6 was introduced
in 2001 were much lighter and used much less JavaScript than those created in 2005.
The difference in the amount of JavaScript code became clear as the IE 6 JavaScript
engine struggled to keep up due to its static garbage-collection routine. The engine
looked for a fixed number of objects in memory to determine when to collect garbage.
Earlier web application developers had run into this threshold infrequently, but with
more JavaScript code comes more objects, and complex web applications began to hit
this threshold quite often. The problem became clear: JavaScript developers and web
applications had evolved while the JavaScript engines had not.
Although other browsers had more logical garbage collection routines, and somewhat
better runtime performance, most still used a JavaScript interpreter to execute code.
Code interpretation is inherently slower than compilation since there’s a translation
process between the code and the computer instructions that must be run. No matter
how smart and optimized interpreters get, they always incur a performance penalty.
Compilers are filled with all kinds of optimizations that allow developers to write code
in whatever way they want without worrying whether it’s optimal. The compiler can
determine, based on lexical analysis, what the code is attempting to do and then optimize it by producing the fastest-running machine code to complete the task. Interpreters have few such optimizations, which frequently means that code is executed exactly
as it is written.
In effect, JavaScript forces the developer to perform the optimizations that a compiler
would normally handle in other languages.
xii | Preface
Next-Generation JavaScript Engines
In 2008, JavaScript engines got their first big performance boost. Google introduced
their brand-new browser called Chrome. Chrome was the first browser released with
an optimizing JavaScript engine, codenamed V8. The V8 JavaScript engine is a just-intime (JIT) compilation engine for JavaScript, which produces machine code from JavaScript code and then executes it. The resulting experience is blazingly fast JavaScript
execution.
Other browsers soon followed suit with their own optimizing JavaScript engines. Safari
4 features the Squirrel Fish Extreme (also called Nitro) JIT JavaScript engine, and Firefox 3.5 includes the TraceMonkey engine, which optimizes frequently executed code
paths.
With these newer JavaScript engines, optimizations are being done at the compilerlevel, where they should be done. Someday, developers may be completely free of worry
about performance optimizations in their code. That day, however, is still not here.
Performance Is Still a Concern
Despite advancements in core JavaScript execution time, there are still aspects of JavaScript that these new engines don’t handle. Delays caused by network latency and
operations affecting the appearance of the page are areas that have yet to be adequately
optimized by browsers. While simple optimizations such as function inlining, code
folding, and string concatenation algorithms are easily optimized in compilers, the dynamic and multifaceted structure of web applications means that these optimizations
solve only part of the performance problem.
Though newer JavaScript engines have given us a glimpse into the future of a much
faster Internet, the performance lessons of today will continue to be relevant and important for the foreseeable future.
The techniques and approaches taught in this book address many different aspects of
JavaScript, covering execution time, downloading, interaction with the DOM, page life
cycle, and more. Of these topics only a small subset, those related to core (ECMAScript)
performance, could be rendered irrelevant by advances in JavaScript engines, but that
has yet to happen.
The other topics cover ground where faster JavaScript engines won’t help: DOM interaction, network latency, blocking and concurrent downloading of JavaScript, and
more. These topics will not only continue to be relevant, but will become areas of
further focus and research as low-level JavaScript execution time continues to improve.
Preface | xiii