└── README.md /README.md: -------------------------------------------------------------------------------- 1 | This is my summary of the (JavaScript: The Good Parts By Douglas Crockford)[http://shop.oreilly.com/product/9780596517748.do]. I use it while learning and as quick reference. It is not intended to be an standalone substitution of the book so if you really want to learn the concepts here presented, buy and read the book and use this repository as a reference and guide. 2 | 3 | If you are the publisher and think this repository should not be public, just write me an email at hugomatilla [at] gmail [dot] com and I will make it private. 4 | 5 | Contributions: Issues, comments and pull requests are super welcome 😃 6 | # 1.Table of Contents 7 | 8 | 9 | - [1.Table of Contents](#1table-of-contents) 10 | - [2.Grammar](#2grammar) 11 | - [White Space](#white-space) 12 | - [Name](#name) 13 | - [Reserved Words](#reserved-words) 14 | - [Avoid also these ones](#avoid-also-these-ones) 15 | - [And these](#and-these) 16 | - [Numbers](#numbers) 17 | - [Strings](#strings) 18 | - [Statements](#statements) 19 | - [`var` Statements](#var-statements) 20 | - [Statements](#statements-1) 21 | - [Disruptive Statements](#disruptive-statements) 22 | - [Block](#block) 23 | - [If Statement](#if-statement) 24 | - [Swith Statements](#swith-statements) 25 | - [Case Clause](#case-clause) 26 | - [While Statement](#while-statement) 27 | - [For Statement](#for-statement) 28 | - [Do Statement](#do-statement) 29 | - [Try Statement](#try-statement) 30 | - [Throw Statement](#throw-statement) 31 | - [Return Statement](#return-statement) 32 | - [Break Statement](#break-statement) 33 | - [Expression Statement](#expression-statement) 34 | - [Expressions](#expressions) 35 | - [#Operands precedence](#operands-precedence) 36 | - [Prefix Operator](#prefix-operator) 37 | - [Infix operator](#infix-operator) 38 | - [Invoaction](#invoaction) 39 | - [Refinement](#refinement) 40 | - [Literals](#literals) 41 | - [Object Literal](#object-literal) 42 | - [Regex Literal](#regex-literal) 43 | - [Functions](#functions) 44 | - [Function Literal](#function-literal) 45 | - [Parameters](#parameters) 46 | - [Function body](#function-body) 47 | - [3.Objects](#3objects) 48 | - [Object Literals](#object-literals) 49 | - [Retrieval](#retrieval) 50 | - [Update](#update) 51 | - [Reference](#reference) 52 | - [Prototype](#prototype) 53 | - [Reflection](#reflection) 54 | - [Enumeration](#enumeration) 55 | - [Delete](#delete) 56 | - [Global Abatement](#global-abatement) 57 | - [4.Functions](#4functions) 58 | - [Function Objects](#function-objects) 59 | - [Function Literals](#function-literals) 60 | - [Invocation](#invocation) 61 | - [The Method Invocation Pattern](#the-method-invocation-pattern) 62 | - [The Function Invocation Pattern](#the-function-invocation-pattern) 63 | - [The Constructor Invocation Pattern](#the-constructor-invocation-pattern) 64 | - [The Apply Invocation Pattern](#the-apply-invocation-pattern) 65 | - [Arguments](#arguments) 66 | - [Return](#return) 67 | - [Exceptions](#exceptions) 68 | - [Augmenting Types](#augmenting-types) 69 | - [Recursion](#recursion) 70 | - [Scope](#scope) 71 | - [Closure](#closure) 72 | - [Callbacks](#callbacks) 73 | - [Module](#module) 74 | - [Cascade](#cascade) 75 | - [Curry](#curry) 76 | - [Memoization](#memoization) 77 | - [5. Inheritance](#5-inheritance) 78 | - [Pseudo Classical](#pseudo-classical) 79 | - [Object Specifiers](#object-specifiers) 80 | - [Prototypal](#prototypal) 81 | - [Functional](#functional) 82 | - [Sample](#sample) 83 | - [6 Arrays](#6-arrays) 84 | - [Array Literals](#array-literals) 85 | - [Length](#length) 86 | - [Delete](#delete-1) 87 | - [Enumeration](#enumeration-1) 88 | - [Confusion](#confusion) 89 | - [Methods](#methods) 90 | - [Dimensions](#dimensions) 91 | - [8. Methods](#8-methods) 92 | - [Array](#array) 93 | - [`array.concat(item…)`](#arrayconcatitem) 94 | - [`array.join(separator)`](#arrayjoinseparator) 95 | - [`array.pop( )`](#arraypop-) 96 | - [`array.push(item…)`](#arraypushitem) 97 | - [`array.reverse( )`](#arrayreverse-) 98 | - [`array.shift( )`](#arrayshift-) 99 | - [`array.slice(start, end)`](#arrayslicestart-end) 100 | - [`array.sort(comparefn)`](#arraysortcomparefn) 101 | - [`array.splice(start, deleteCount, item…)`](#arraysplicestart-deletecount-item) 102 | - [`array.unshift(item…)`](#arrayunshiftitem) 103 | - [Function](#function) 104 | - [`function.apply(thisArg, argArray)`](#functionapplythisarg-argarray) 105 | - [Number](#number) 106 | - [`number.toExponential(fractionDigits)`](#numbertoexponentialfractiondigits) 107 | - [`number.toFixed(fractionDigits)`](#numbertofixedfractiondigits) 108 | - [`number.toPrecision(precision)`](#numbertoprecisionprecision) 109 | - [`number.toString(radix)`](#numbertostringradix) 110 | - [Object](#object) 111 | - [`object.hasOwnProperty(name)`](#objecthasownpropertyname) 112 | - [RegExp](#regexp) 113 | - [`regexp.exec(string)`](#regexpexecstring) 114 | - [```regexp.test(string)```](#regexpteststring) 115 | - [String](#string) 116 | - [`string.charAt(pos)`](#stringcharatpos) 117 | - [`string.charCodeAt(pos)`](#stringcharcodeatpos) 118 | - [`string.concat(string…)`](#stringconcatstring) 119 | - [`string.indexOf(searchString, position)`](#stringindexofsearchstring-position) 120 | - [`string.lastIndexOf(searchString, position)`](#stringlastindexofsearchstring-position) 121 | - [`string.localeCompare(that)`](#stringlocalecomparethat) 122 | - [`string.match(regexp)`](#stringmatchregexp) 123 | - [`string.replace(searchValue,replaceValue)`](#stringreplacesearchvaluereplacevalue) 124 | - [`string.search(regexp)`](#stringsearchregexp) 125 | - [`string.slice(start, end)`](#stringslicestart-end) 126 | - [`string.split(separator, limit)`](#stringsplitseparator-limit) 127 | - [`string.substring(start, end)`](#stringsubstringstart-end) 128 | - [`string.toLocaleLowerCase( )`](#stringtolocalelowercase-) 129 | - [`string.toLocaleUpperCase( )`](#stringtolocaleuppercase-) 130 | - [`string.toLowerCase( )`](#stringtolowercase-) 131 | - [`string.toUpperCase( )`](#stringtouppercase-) 132 | - [`String.fromCharCode(char…)`](#stringfromcharcodechar) 133 | - [Awful Parts](#awful-parts) 134 | - [Global Variables](#global-variables) 135 | - [Scope](#scope-1) 136 | - [Semicolon Insertion](#semicolon-insertion) 137 | - [Reserved Words](#reserved-words-1) 138 | - [Unicode](#unicode) 139 | - [typeof](#typeof) 140 | - [parseInt](#parseint) 141 | - [+](#) 142 | - [Floating Point](#floating-point) 143 | - [NaN](#nan) 144 | - [Phony Arrays](#phony-arrays) 145 | - [Falsy Values](#falsy-values) 146 | - [`hasOwnProperty`](#hasownproperty) 147 | - [Object](#object-1) 148 | - [Bad Parts](#bad-parts) 149 | - [==](#) 150 | - [`with` Statement](#with-statement) 151 | - [`eval`](#eval) 152 | - [`continue` Statement](#continue-statement) 153 | - [`switch` Fall Through](#switch-fall-through) 154 | - [Block-less Statements](#block-less-statements) 155 | - [`++` `--`](#---) 156 | - [Bitwise Operators](#bitwise-operators) 157 | - [The function Statement Versus the function Expression](#the-function-statement-versus-the-function-expression) 158 | - [Typed Wrappers](#typed-wrappers) 159 | - [`void`](#void) 160 | - [JSLint](#jslint) 161 | - [Undefined Variables and Functions](#undefined-variables-and-functions) 162 | - [Members](#members) 163 | - [Options](#options) 164 | - [Semicolon](#semicolon) 165 | - [Line Breaking](#line-breaking) 166 | - [Comma](#comma) 167 | - [Required Blocks](#required-blocks) 168 | - [Forbidden Blocks](#forbidden-blocks) 169 | - [Expression Statements](#expression-statements) 170 | - [`for in` Statement](#for-in-statement) 171 | - [`switch` Statement](#switch-statement) 172 | - [var Statement](#var-statement) 173 | - [with Statement](#with-statement) 174 | - [`=`](#) 175 | - [`==` and `!=`](#-and-) 176 | - [Labels](#labels) 177 | - [Confusing Pluses and Minuses](#confusing-pluses-and-minuses) 178 | - [++ and --](#-and---) 179 | - [Bitwise Operators](#bitwise-operators-1) 180 | - [`eval` Is Evil](#eval-is-evil) 181 | - [`void`](#void-1) 182 | - [Regular Expressions](#regular-expressions) 183 | - [Constructors and new](#constructors-and-new) 184 | - [Not Looked For](#not-looked-for) 185 | - [HTML](#html) 186 | - [JSON](#json) 187 | - [Report](#report) 188 | - [JSON](#json-1) 189 | - [JSON syntax](#json-syntax) 190 | - [Using JSON Securely](#using-json-securely) 191 | 192 | 193 | # 2.Grammar 194 | ## White Space 195 | ![alt text][space] 196 | ## Name 197 | Names are used for statements, variables, parameters, property names, operators, and labels. 198 | ![alt text][name] 199 | 200 | ### Reserved Words 201 | | | | | | 202 | | -------- | ---------- | ---------- | ------------ | 203 | | abstract | else | instanceof | super | 204 | | boolean | enum | int | switch | 205 | | break | export | interface | synchronized | 206 | | byte | extends | let | this | 207 | | case | FALSE | long | throw | 208 | | catch | final | native | throws | 209 | | char | finally | new | transient | 210 | | class | float | null | TRUE | 211 | | const | for | package | try | 212 | | continue | function | private | typeof | 213 | | debugger | goto | protected | var | 214 | | default | if | public | void | 215 | | delete | implements | return | volatile | 216 | | do | import | short | while | 217 | | double | in | static | with | 218 | 219 | #### Avoid also these ones 220 | 221 | | | | | 222 | | ------------------ | ------------------ | -------------- | 223 | | alert | frames | outerHeight | 224 | | all | frameRate | outerWidth | 225 | | anchor | function | packages | 226 | | anchors | getClass | pageXOffset | 227 | | area | hasOwnProperty | pageYOffset | 228 | | Array | hidden | parent | 229 | | assign | history | parseFloat | 230 | | blur | image | parseInt | 231 | | button | images | password | 232 | | checkbox | Infinity | pkcs11 | 233 | | clearInterval | isFinite | plugin | 234 | | clearTimeout | isNaN | prompt | 235 | | clientInformation | isPrototypeOf | propertyIsEnum | 236 | | close | java | prototype | 237 | | closed | JavaArray | radio | 238 | | confirm | JavaClass | reset | 239 | | constructor | JavaObject | screenX | 240 | | crypto | JavaPackage | screenY | 241 | | Date | innerHeight | scroll | 242 | | decodeURI | innerWidth | secure | 243 | | decodeURIComponent | layer | select | 244 | | defaultStatus | layers | self | 245 | | document | length | setInterval | 246 | | element | link | setTimeout | 247 | | elements | location | status | 248 | | embed | Math | String | 249 | | embeds | mimeTypes | submit | 250 | | encodeURI | name | taint | 251 | | encodeURIComponent | NaN | text | 252 | | escape | navigate | textarea | 253 | | eval | navigator | top | 254 | | event | Number | toString | 255 | | fileUpload | Object | undefined | 256 | | focus | offscreenBuffering | unescape | 257 | | form | open | untaint | 258 | | forms | opener | valueOf | 259 | | frame | option | window | 260 | 261 | #### And these 262 | 263 | | | | | | 264 | | -------------- | ---------- | ----------- | ----------- | 265 | | onbeforeunload | ondragdrop | onkeyup | onmouseover | 266 | | onblur | onerror | onload | onmouseup | 267 | | ondragdrop | onfocus | onmousedown | onreset | 268 | | onclick | onkeydown | onmousemove | onsubmit | 269 | | oncontextmenu | onkeypress | onmouseout | onunload | 270 | 271 | ## Numbers 272 | Only one number type. 64-bit floating point. (Java double) 273 | 274 | `NaN` is a number of an operation that cannot produce a normal result. Use `isNaN(number)` to detect it. 275 | 276 | `Infinity` represents all values greater than `1.79769313486231570e+308`. 277 | 278 | ![alt text][numbers] 279 | ![alt text][integer] 280 | ![alt text][fraction] 281 | ![alt text][exponent] 282 | 283 | 284 | ## Strings 285 | Strings can be wrapped in single quotes or double quotes. 286 | The `\` (backslash) is the escape character. 287 | Characters in JavaScript are 16 bits wide. 288 | 289 | ![alt text][string] 290 | 291 | Escape sequences allow for inserting characters into strings that are not normally permitted 292 | ![alt text][escaped] 293 | 294 | Strings have a `length` property 295 | 296 | Strings are immutable. 297 | 298 | 299 | ## Statements 300 | ### `var` Statements 301 | A compilation unit contains a set of executable statements. 302 | ![alt text][var] 303 | ### Statements 304 | ![alt text][statements] 305 | ### Disruptive Statements 306 | ![alt text][disruptive] 307 | ### Block 308 | `Blocks` in JavaScript do not create a new scope, so variables should be defined at the top of the function, not in blocks. 309 | ![alt text][block] 310 | ### If Statement 311 | ![alt text][if] 312 | False values: 313 | * `false` 314 | * `null` 315 | * `undefined` 316 | * The empty string '' 317 | * The number 0 318 | * The number `NaN` 319 | All other values are truthy, including true, the string 'false', and all objects. 320 | 321 | ### Swith Statements 322 | ![alt text][switch] 323 | ### Case Clause 324 | ![alt text][case] 325 | ### While Statement 326 | ![alt text][while] 327 | ### For Statement 328 | ![alt text][for] 329 | ### Do Statement 330 | ![alt text][do] 331 | ### Try Statement 332 | ![alt text][try] 333 | ### Throw Statement 334 | ![alt text][throw] 335 | ### Return Statement 336 | ![alt text][return] 337 | ### Break Statement 338 | ![alt text][break] 339 | ### Expression Statement 340 | ![alt text][expression-statement] 341 | 342 | ## Expressions 343 | ![alt text][expression] 344 | 345 | The simplest expressions are: 346 | 347 | * a literal value (such as a string or number) 348 | * a variable 349 | * a built-in value (true, false, null, undefined, NaN, or Infinity) 350 | * an invocation expression preceded by new 351 | * a refinement expression preceded by delete 352 | * an expression wrapped in parentheses 353 | * an expression preceded by a prefix operator 354 | * an expression followed by: 355 | * An infix operator and another expression 356 | * The ? ternary operator followed by another expression, then by :, and then byyet another expression 357 | * An invocation 358 | * A refinement 359 | 360 | 361 | 362 | ### #Operands precedence 363 | | . [] ( ) | Refinement and invocation | 364 | | delete new typeof + - ! | Unary operators | 365 | | * / % | Multiplication, division, modulo | 366 | | + - | Addition/concatenation, subtraction | 367 | | >= <= > < | Inequality | 368 | | === !== | Equality | 369 | | && | Logical and | 370 | | || | Logical or | 371 | | ?: | Ternary | 372 | 373 | ### Prefix Operator 374 | 375 | ![alt text][prefix] 376 | 377 | The values produced by typeof are 'number', 'string', 'boolean', 'undefined','function', and 'object'. If the operand is an array or null, then the result is 'object', which is wrong. 378 | 379 | The + operator adds or concatenates. If you want it to add, make sure both operands are numbers. 380 | 381 | The / operator can produce a noninteger result even if both operands are integers. 382 | 383 | ### Infix operator 384 | ![alt text][infix] 385 | 386 | ### Invoaction 387 | Invocation causes the execution of a function value. 388 | ![alt text][invocation] 389 | 390 | ### Refinement 391 | Specify a property or element of an object or array 392 | ![alt text][refinement] 393 | 394 | ## Literals 395 | ![alt text][literal] 396 | ### Object Literal 397 | ![alt text][object-literal] 398 | ### Regex Literal 399 | ![alt text][regexp-literal] 400 | 401 | 402 | ## Functions 403 | ### Function Literal 404 | ![alt text][function-literal] 405 | A function literal defines a function value. 406 | 407 | It can have an optional name that it can use to call itself recursively. 408 | 409 | ### Parameters 410 | ![alt text][parameters] 411 | ### Function body 412 | ![alt text][function-body] 413 | 414 | 415 | 416 | # 3.Objects 417 | Numbers, strings, and booleans are not objects the rest are. 418 | 419 | Numbers, strings, and booleans are object-like in that they have methods, but they are immutable. 420 | 421 | Objects in JavaScript are mutable keyed collections. 422 | 423 | An object is a container of properties, where a property has a name and a value. 424 | 425 | * A property name can be any string, including the empty string. 426 | * A property value can be any JavaScript value except for `undefined`. 427 | 428 | Objects in JavaScript are class-free. 429 | 430 | JavaScript includes a prototype linkage feature that allows one object to inherit the properties of another. 431 | 432 | ## Object Literals 433 | An object literal is a pair of curly braces surrounding zero or more name/value pairs. 434 | 435 | ```js 436 | var empty_object = {}; 437 | 438 | var stooge = { 439 | "first-name": "Jerome", 440 | "last-name": "Howard" 441 | }; 442 | 443 | ``` 444 | 445 | ## Retrieval 446 | Values can be retrieved from an object by wrapping a string expression in a [ ] suffix. 447 | 448 | Dot `.` notation can be use if the string expression is a constant, legal and not a reserved word. 449 | 450 | `undefined` value is produced if an attempt is made to retrieve a nonexistent member. 451 | ```js 452 | stooge.middle-name //undefined 453 | 454 | ``` 455 | 456 | `||` can be used to fill default values 457 | 458 | ```js 459 | var middle = stooge["middle-name"] || "(none)"; 460 | 461 | ``` 462 | 463 | `&&` to avoid TypeError exception when retrieving values from `undefined` 464 | ```js 465 | flight.equipment // undefined 466 | flight.equipment.model // throw "TypeError" 467 | flight.equipment && flight.equipment.model // undefined 468 | ``` 469 | 470 | ## Update 471 | Updated by assignment. If exists it changes if not it is added. 472 | ```js 473 | stooge['first-name'] = 'Jerome'; 474 | ``` 475 | ## Reference 476 | Objects are passed around by reference. They are never copied 477 | 478 | ## Prototype 479 | Every object is linked to a prototype object from which it can inherit properties. 480 | 481 | All Objects are linked to `Object.prototype`, an object that comes standard with JavaScript. 482 | 483 | When you make a new object, you can select the object that should be its prototype. 484 | 485 | ## Reflection 486 | Use `typeof` to determine what properties an object has. 487 | 488 | `hasOwnProperty` method, which returns true if the object has a particular property. It does not look at the prototype chain 489 | 490 | ```js 491 | flight.hasOwnProperty('number') // true 492 | flight.hasOwnProperty('constructor') // false 493 | ``` 494 | 495 | ## Enumeration 496 | The for in statement can loop over all of the property names in an object, including functions and prototype properties that you might not be interested. 497 | 498 | Filter them using `typeof`. The order will not be guaranteed 499 | 500 | ```js 501 | var name; 502 | for (name in another_stooge) { 503 | if (typeof another_stooge[name] !== 'function') { 504 | document.writeln(name + ': ' + another_stooge[name]); 505 | } 506 | } 507 | ``` 508 | ## Delete 509 | `delete` removes a property from an object. 510 | 511 | ## Global Abatement 512 | JavaScript makes it easy to define global variables but they weaken the resiliency of programs and should be avoided. 513 | 514 | Create a single global variable for your application: 515 | ```js 516 | var MYAPP = {}; 517 | MYAPP.stooge = { 518 | "first-name": "Joe", 519 | "last-name": "Howard" 520 | }; 521 | MYAPP.flight = { 522 | airline: "Oceanic", 523 | number: 815, 524 | ... 525 | }; 526 | ``` 527 | 528 | By reducing your global footprint to a single name, you significantly reduce the chance of bad interactions with other applications, widgets, or libraries. 529 | 530 | 531 | # 4.Functions 532 | ## Function Objects 533 | * Functions are objects. 534 | * Objects are collections of name/value pairs. 535 | * Objects have a hidden link to a prototype object. 536 | * Objects produced from object literals are linked to Object.prototype. 537 | * Function objects are linked to Function.prototype (which is linked to Object.prototype) 538 | * Every function is created with two additional hidden properties: 539 | *the function’s context 540 | *the code that implements the function’s behavior. 541 | * Every function object is created with a `prototype` property. Its value is an object with a `constructor` property whose value is the function. This is distinct from the hidden link to Function.prototype. 542 | * Functions (because they are objects) can be: 543 | * stored in variables, objects, and arrays. 544 | * passed as arguments to functions 545 | * returned from functions. 546 | * have methods. 547 | 548 | The special thing about functions is that they can be invoked. 549 | 550 | ## Function Literals 551 | Function objects are created with function literals: 552 | 553 | ```js 554 | var add = function (a, b) { 555 | return a + b; 556 | }; 557 | ``` 558 | 559 | A function literal has four parts: 560 | 561 | * 1. reserved word `function`. 562 | * 2. The optional function’s name. If no name, it is called `anonymous function`. 563 | * 3. Set of parameters wrapped in parentheses. 564 | * 4. A set of statements wrapped in curly braces. These statements are the body of the function. They are executed when the function is invoked. 565 | 566 | **Closure** A link to the outer function context. 567 | 568 | ## Invocation 569 | Invoking a function suspends the execution of the current function, passing control and parameters to the new function. In addition to the declared parameters, every 570 | function receives two additional parameters: `this` and `arguments`. 571 | 572 | `this`:is determined by the invocation pattern. 573 | There are four patterns of invocation in JavaScript: 574 | 575 | * the method invocation pattern, 576 | * the function invocation pattern, 577 | * the constructor invocation pattern, 578 | * the apply invocation pattern. 579 | 580 | The patterns differ in how the bonus parameter this is initialized. 581 | 582 | ### The Method Invocation Pattern 583 | When a function is stored as a property of an object, we call it a method. 584 | 585 | When a method is invoked, this is bound to that object. 586 | If an invocation expression contains a refinement (that is, a . dot expression or [subscript] expression), it is 587 | invoked as a method: 588 | 589 | ```js 590 | myObject.increment(2); 591 | ``` 592 | The binding of `this` to the object happens at invocation time. 593 | 594 | Methods that get their object context from this are called public methods. 595 | ### The Function Invocation Pattern 596 | When a function is not the property of an object, then it is invoked as a function: 597 | 598 | ```js 599 | var sum = add(3, 4); // sum is 7 600 | ``` 601 | When a function is invoked with this pattern, `this` is bound to the global object. It should be to the outer function. 602 | 603 | Defining a variable and assigns it the value of `this` will make the trick. 604 | 605 | By convention, the name of that variable is that: 606 | ```js 607 | // Augment myObject with a double method. 608 | myObject.double = function ( ) { 609 | var that = this; // Workaround. 610 | var helper = function ( ) { 611 | that.value = add(that.value, that.value); 612 | }; 613 | helper( ); // Invoke helper as a function. 614 | }; 615 | ``` 616 | 617 | ### The Constructor Invocation Pattern 618 | If a function is invoked with the new prefix, then a new object will be created with a hidden link to the value of the function’s prototype member, and this will be bound 619 | to that new object. 620 | 621 | Use of this style of constructor functions is not recommended. 622 | 623 | ```js 624 | var Quo = function (string) { 625 | this.status = string; 626 | } 627 | 628 | Quo.prototype.get_status = function ( ) { 629 | return this.status; 630 | } 631 | 632 | var myQuo = new Quo("confused"); 633 | document.writeln(myQuo.get_status( )); // confused 634 | 635 | ``` 636 | 637 | ### The Apply Invocation Pattern 638 | Functions can have methods. 639 | 640 | The apply method lets us construct an array of arguments to use to invoke a function. 641 | 642 | It also lets us choose the value of this. 643 | 644 | The apply method takes two parameters. 645 | 646 | The first is the value that should be bound to this. 647 | 648 | The second is an array of parameters. 649 | 650 | ```js 651 | var array = [3, 4]; 652 | var sum = add.apply(null, array); // sum is 7 653 | 654 | var statusObject = { 655 | status: 'A-OK' 656 | }; 657 | // statusObject does not inherit from Quo.prototype, 658 | // but we can invoke the get_status method on 659 | // statusObject even though statusObject does not have 660 | // a get_status method. 661 | var status = Quo.prototype.get_status.apply(statusObject); 662 | // status is 'A-OK' 663 | ``` 664 | 665 | ### Arguments 666 | A bonus parameter that is available to functions when they are invoked is the arguments array. It gives the function access to all of the arguments that were supplied 667 | with the invocation, including excess arguments that were not assigned to 668 | parameters. 669 | ```js 670 | var sum = function ( ) { 671 | var i, sum = 0; 672 | for (i = 0; i < arguments.length; i += 1) { 673 | sum += arguments[i]; 674 | } 675 | return sum; 676 | }; 677 | document.writeln(sum(4, 8, 15, 16, 23, 42)); // 108 678 | ``` 679 | 680 | `arguments` is not really an array. It is an array-like object.`arguments` has a length property, but it lacks all of the array methods. 681 | 682 | ## Return 683 | When a function is invoked, it begins execution with the first statement, and ends when it hits the } that closes the function body. 684 | 685 | That causes the function to return control to the part of the program that invoked the function. 686 | 687 | The return statement can be used to cause the function to return early. When return is executed, the function returns immediately without executing the remaining statements. 688 | 689 | A function always returns a value. If the return value is not specified, then undefined is returned. 690 | 691 | If the function was invoked with the new prefix and the return value is not an object, then this (the new object) is returned instead 692 | 693 | ## Exceptions 694 | 695 | ```js var add = function (a, b) { 696 | if (typeof a !== 'number' || typeof b !== 'number') { 697 | throw { 698 | name: 'TypeError', 699 | message: 'add needs numbers' 700 | }; 701 | } 702 | return a + b; 703 | } 704 | ``` 705 | The throw statement interrupts execution of the function. 706 | 707 | It should be given an exception object containing a name and message. 708 | The exception object will be delivered to the catch clause of a try statement: 709 | 710 | ```js 711 | var try_it = function ( ) { 712 | try { 713 | add("seven"); 714 | } catch (e) { 715 | document.writeln(e.name + ': ' + e.message); 716 | } 717 | } 718 | try_it( ); 719 | ``` 720 | A try statement has a single catch block that will catch all exceptions. 721 | 722 | The exception handler will have to inspect the name to determine the type of the exception. 723 | 724 | ## Augmenting Types 725 | JavaScript allows the basic types of the language to be augmented. 726 | 727 | 728 | For example, by augmenting `Function.prototype`, we can make a method available to all functions: 729 | ```js 730 | Function.prototype.method = function (name, func) { 731 | this.prototype[name] = func; 732 | return this; 733 | }; 734 | ``` 735 | 736 | ```js 737 | Number.method('integer', function ( ) { 738 | return Math[this < 0 ? 'ceiling' : 'floor'](this); 739 | }); 740 | document.writeln((-10 / 3).integer( )); // -3 741 | ``` 742 | The prototypes of the basic types are public structures, so care must be taken when mixing libraries. One defensive technique is to add a method only if the method is 743 | known to be missing: 744 | 745 | ```js 746 | Function.prototype.method = function (name, func) { 747 | if (!this.prototype[name]) { 748 | this.prototype[name] = func; 749 | } 750 | }; 751 | ``` 752 | 753 | ## Recursion 754 | A recursive function is a function that calls itself, either directly or indirectly. 755 | 756 | Recursion is a powerful programming technique in which a problem is divided into a set of similar subproblems, each solved with a trivial solution. 757 | 758 | ## Scope 759 | Scope in a programming language controls the visibility and lifetimes of variables and parameters. 760 | 761 | ```js 762 | var foo = function ( ) { 763 | var a = 3, b = 5; 764 | var bar = function ( ) { 765 | 766 | var b = 7, c = 11; 767 | // At this point, a is 3, b is 7, and c is 11 768 | 769 | a += b + c; 770 | // At this point, a is 21, b is 7, and c is 11 771 | }; 772 | // At this point, a is 3, b is 5, and c is not defined 773 | 774 | bar( ); 775 | // At this point, a is 21, b is 5 776 | }; 777 | ``` 778 | JavaScript does not have block scope. 779 | 780 | JavaScript does have function scope. The parameters and variables defined in a function are not visible outside of the function, and that a variable defined anywhere within a function is visible everywhere within the function 781 | 782 | ## Closure 783 | The good news about scope is that inner functions get access to the parameters and variables of the functions they are defined within (with the exception of this and 784 | arguments). This is a very good thing. 785 | 786 | ```js 787 | var quo = function (status) { 788 | return { 789 | get_status: function ( ) { 790 | return status; 791 | } 792 | }; 793 | }; 794 | // Make an instance of quo. 795 | 796 | var myQuo = quo("amazed"); 797 | 798 | console.log(myQuo.get_status( )); 799 | 800 | 801 | ``` 802 | When we call quo, it returns a new object containing a `get_status` method. 803 | 804 | A reference to that object is stored in myQuo. 805 | 806 | The `get_status` method still has privileged access to quo’s `status` property even though quo has already returned. 807 | 808 | `get_status` does not have access to a copy of the parameter; it has access to the parameter itself. 809 | 810 | This is possible because the function has access to the context in which it was created. This is called **closure**. 811 | 812 | ## Callbacks 813 | Functions can make it easier to deal with discontinuous events. 814 | 815 | ```js 816 | request = prepare_the_request( ); 817 | send_request_asynchronously(request, function (response) { 818 | display(response); 819 | }); 820 | ``` 821 | We pass a function parameter to the `send_request_asynchronously` function that will be called when the response is available. 822 | 823 | ## Module 824 | A module is a function or object that presents an interface but that hides its state and implementation. 825 | 826 | By using functions to produce modules, we can almost completely eliminate our use of global variables, thereby mitigating one of JavaScript’s worst features. 827 | 828 | The module pattern takes advantage of function scope and closure to create relationships that are binding and private. In this example, only the deentityify method has access to the entity data structure. 829 | 830 | The general pattern of a module is a function that defines private variables and functions; creates privileged functions which, through closure, will have access to the private variables and functions; and that returns the privileged functions or stores them in an accessible place. 831 | 832 | Use of the module pattern can eliminate the use of global variables. It promotes information hiding and other good designs practices. 833 | 834 | ```js 835 | var serial_maker = function ( ) { 836 | var prefix = ''; 837 | var seq = 0; 838 | return { 839 | set_prefix: function (p) { 840 | prefix = String(p); 841 | }, 842 | set_seq: function (s) { 843 | seq = s; 844 | }, 845 | gensym: function ( ) { 846 | var result = prefix + seq; 847 | seq += 1; 848 | return result; 849 | } 850 | }; 851 | }; 852 | var seqer = serial_maker( ); 853 | seqer.set_prefix = ('Q';) 854 | seqer.set_seq = (1000); 855 | var unique = seqer.gensym( ); // unique is "Q1000" 856 | ``` 857 | 858 | The methods do not make use of this or that. As a result, there is no way to compromise the `seqer`. 859 | 860 | It isn’t possible to get or change the `prefix` or `seq` except as permitted by the methods. 861 | 862 | The seqer object is mutable, so the methods could be replaced, but that still does not give access to its secrets. 863 | 864 | `seqer` is simply a collection of functions, and those functions are capabilities that grant specific powers to use or modify the secret state. 865 | 866 | If we passed `seqer.gensym` to a third party’s function, that function would be able to generate unique strings, but would be unable to change the prefix or seq. 867 | 868 | 869 | ## Cascade 870 | Some methods do not have a return value. 871 | 872 | If we have those methods return this instead of undefined, we can enable cascades. 873 | 874 | ```js 875 | getElement('myBoxDiv'). 876 | move(350, 150). 877 | width(100). 878 | height(100). 879 | color('red'). 880 | border('10px outset') 881 | ``` 882 | 883 | ## Curry 884 | Functions are values, and we can manipulate function values in interesting ways. 885 | 886 | Currying allows us to produce a new function by combining a function and an argument: 887 | 888 | ```js 889 | var add1 = add.curry(1); 890 | document.writeln(add1(6)); //7 891 | ``` 892 | 893 | JavaScript does not have a curry method, but we can fix that by augmenting Function.prototype: 894 | ```js 895 | Function.method('curry', function ( ) { 896 | var slice = Array.prototype.slice, 897 | args = slice.apply(arguments), 898 | that = this; 899 | return function ( ) { 900 | return that.apply(null, args.concat(slice.apply(arguments))); 901 | }; 902 | }); 903 | ``` 904 | 905 | ## Memoization 906 | Functions can use objects to remember the results of previous operations, making it possible to avoid unnecessary work. 907 | 908 | This optimization is called **memoization**. 909 | 910 | 911 | We will keep our memoized results in a memo array that we can hide in a closure. 912 | 913 | When our function is called, it first looks to see if it already knows the result. 914 | 915 | If it does, it can immediately return it: 916 | ```js 917 | var fibonacci = function ( ) { 918 | var memo = [0, 1]; 919 | var fib = function (n) { 920 | var result = memo[n]; 921 | if (typeof result !== 'number') { 922 | result = fib(n - 1) + fib(n - 2); 923 | memo[n] = result; 924 | } 925 | return result; 926 | }; 927 | return fib; 928 | }( ); 929 | ``` 930 | 931 | A generalized version: 932 | 933 | ```js 934 | var memoizer = function (memo, fundamental) { 935 | var shell = function (n) { 936 | var result = memo[n]; 937 | if (typeof result !== 'number') { 938 | result = fundamental(shell, n); 939 | memo[n] = result; 940 | } 941 | return result; 942 | }; 943 | return shell; 944 | }; 945 | 946 | ``` 947 | ```js 948 | var fibonacci = memoizer([0, 1], function (shell, n) { 949 | return shell(n - 1) + shell(n - 2); 950 | }); 951 | ``` 952 | 953 | # 5. Inheritance 954 | In classical languages, objects are instances of classes, and a class can inherit from another class. JavaScript is a prototypal language, which means that objects inherit directly from other objects. 955 | 956 | ## Pseudo Classical 957 | A much better alternative is to not use new at all. 958 | 959 | The pseudoclassical form can provide comfort to programmers who are unfamiliar 960 | 961 | The classically inspired notation can induce programmers to compose hierarchies that are unnecessarily deep and complicated. 962 | 963 | Much of the complexity of class hierarchies is motivated by the constraints of static type checking. JavaScript is completely free of those constraints. 964 | 965 | ## Object Specifiers 966 | Use `makers` when having a lot of arguments in the constructor of an object. 967 | 968 | So, instead of: 969 | ```js 970 | var myObject = maker(f, l, m, c, s); 971 | ``` 972 | 973 | we can write: 974 | ```js 975 | var myObject = maker({ 976 | first: f, 977 | last: l, 978 | state: s, 979 | city: c 980 | }); 981 | ``` 982 | 983 | We could also use a JSON with all the parameters as the argument. 984 | 985 | ## Prototypal 986 | Contrary to purely prototypal pattern, where we dispense with classes, in JavaScript we focus on the objects. 987 | 988 | A new object can inherit the properties of an old object. 989 | 990 | ```js 991 | var myMammal = { 992 | name : 'Herb the Mammal', 993 | get_name : function ( ) { 994 | return this.name; 995 | }, 996 | says : function ( ) { 997 | return this.saying || ''; 998 | } 999 | }; 1000 | ``` 1001 | Using `create` from Chapter 3 1002 | 1003 | ```js 1004 | var myCat = Object.create(myMammal); 1005 | myCat.name = 'Henrietta'; 1006 | myCat.saying = 'meow'; 1007 | myCat.purr = function (n) { 1008 | var i, s = ''; 1009 | for (i = 0; i < n; i += 1) { 1010 | if (s) { 1011 | s += '-'; 1012 | } 1013 | s += 'r'; 1014 | } 1015 | return s; 1016 | }; 1017 | myCat.get_name = function ( ) { 1018 | return this.says( ) + ' ' + this.name + ' ' + this.says( ); 1019 | }; 1020 | ``` 1021 | 1022 | This is differential inheritance. By customizing a new object, we specify the differences from the object on which it is based. 1023 | 1024 | ## Functional 1025 | One weakness of the inheritance patterns we have seen so far is that we get no privacy. 1026 | 1027 | We make a function that will produce objects. It contains four steps: 1028 | 1029 | 1. It creates a new object. There are lots of ways to make an object. 1030 | 2. It optionally defines private instance variables and methods. These are just ordinary vars of the function. 1031 | 3. It augments that new object with methods. Those methods will have privileged access to the parameters and the vars defined in the second step. 1032 | 4. It returns that new object. 1033 | 1034 | ```js 1035 | var constructor = function (spec, my) { 1036 | var that, other private instance variables; 1037 | 1038 | my = my || {}; 1039 | // Add shared variables and functions to my 1040 | 1041 | that = a new object; 1042 | //Add privileged methods to that 1043 | 1044 | return that; 1045 | }; 1046 | ``` 1047 | 1048 | 1. The `spec` object contains all of the information that the constructor needs to make an instance. 1049 | 2. The `my` object is a container of secrets that are shared by the constructors in the inheritance chain. 1050 | 3. Declare the private instance variables and private methods for the object. This is done by simply declaring variables. 1051 | 4. Add the shared secrets to the `my` object. 1052 | 5. Make a new object and assign it to `that`. 1053 | 6. Augment that, adding the privileged methods that make up the object’s interface. 1054 | 1055 | ```js 1056 | var methodical = function ( ) { 1057 | ... 1058 | }; 1059 | that.methodical = methodical; 1060 | ``` 1061 | 1062 | 7. Return `that` 1063 | 1064 | 1065 | #### Sample 1066 | The name and saying properties are now completely private. They are accessible only via the privileged get_name and says methods: 1067 | 1068 | ```js 1069 | var mammal = function (spec) { 1070 | var that = {}; 1071 | that.get_name = function ( ) { 1072 | return spec.name; 1073 | }; 1074 | that.says = function ( ) { 1075 | return spec.saying || ''; 1076 | }; 1077 | 1078 | return that; 1079 | }; 1080 | 1081 | var myMammal = mammal({name: 'Herb'}); 1082 | ``` 1083 | 1084 | ```js 1085 | var cat = function (spec) { 1086 | spec.saying = spec.saying || 'meow'; 1087 | var that = mammal(spec); 1088 | 1089 | that.purr = function (n) { 1090 | return 'r'.repeat(n); 1091 | }; 1092 | 1093 | that.get_name = function ( ) { 1094 | return that.says( ) + ' ' + spec.name + ' ' + that.says( ); 1095 | }; 1096 | 1097 | return that; 1098 | }; 1099 | 1100 | var myCat = cat({name: 'Henrietta'}); 1101 | ``` 1102 | 1103 | The functional pattern also gives us a way to deal with super methods. 1104 | 1105 | Make a superior method that takes a method name and returns a function that invokes that method. 1106 | 1107 | ```js 1108 | Object.method('superior', function (name) { 1109 | var that = this, 1110 | method = that[name]; 1111 | return function ( ) { 1112 | return method.apply(that, arguments); 1113 | }; 1114 | }); 1115 | ``` 1116 | 1117 | ```js 1118 | var coolcat = function (spec) { 1119 | var that = cat(spec), 1120 | super_get_name = that.superior('get_name'); 1121 | 1122 | that.get_name = function (n) { 1123 | return 'like ' + super_get_name( ) + ' baby'; 1124 | }; 1125 | 1126 | return that; 1127 | }; 1128 | 1129 | var myCoolCat = coolcat({name: 'Bix'}); 1130 | var name = myCoolCat.get_name( ); 1131 | // 'like meow Bix meow baby' 1132 | ``` 1133 | 1134 | The functional pattern has a great deal of flexibility. 1135 | 1136 | Gives us better encapsulation and information hiding and access to super methods. 1137 | 1138 | # 6 Arrays 1139 | ## Array Literals 1140 | Array literals provide a very convenient notation for creating new array values. 1141 | 1142 | An array literal is a pair of square brackets surrounding zero or more values separated by commas. 1143 | 1144 | Elements of an array are NOT required to be of the same type. 1145 | 1146 | ```js 1147 | var empty = []; 1148 | var numbers = [ 1149 | 'zero', 'one', 'two', 'three', 'four', 1150 | 'five', 'six', 'seven', 'eight', 'nine' 1151 | ]; 1152 | empty[1] // undefined 1153 | numbers[1] // 'one' 1154 | empty.length // 0 1155 | numbers.length // 10 1156 | var misc = [ 1157 | 'string', 98.6, true, false, null, undefined, 1158 | ['nested', 'array'], {object: true}, NaN]; 1159 | ``` 1160 | 1161 | ## Length 1162 | Every array has a length property. 1163 | 1164 | JavaScript’s array length is not an upper bound. 1165 | 1166 | There is no array bounds error. 1167 | 1168 | The length property is the largest integer property name in the array plus one. 1169 | 1170 | This is not necessarily the number of properties in the array: 1171 | 1172 | ```js 1173 | var myArray = []; 1174 | myArray.length // 0 1175 | myArray[1000000] = true; 1176 | myArray.length // 1000001 1177 | // myArray contains one property. 1178 | ``` 1179 | 1180 | The length can be set explicitly. 1181 | 1182 | Making the length larger does not allocate more space for the array. 1183 | 1184 | Making the length smaller will delete elements. 1185 | 1186 | ```js 1187 | numbers.length = 3; 1188 | // numbers is ['zero', 'one', 'two'] 1189 | ``` 1190 | 1191 | A new element can be appended to the end of an array by assigning to the array’s current length: 1192 | ```js 1193 | numbers[numbers.length] = 'shi'; 1194 | // numbers is ['zero', 'one', 'two', 'shi'] 1195 | ``` 1196 | Use push for that 1197 | ```js 1198 | numbers.push('go'); 1199 | // numbers is ['zero', 'one', 'two', 'shi', 'go'] 1200 | ``` 1201 | 1202 | ## Delete 1203 | Since JavaScript’s arrays are really objects, the delete operator can be used to remove elements from an array: 1204 | 1205 | ```js 1206 | delete numbers[2]; 1207 | // numbers is ['zero', 'one', undefined, 'shi', 'go'] 1208 | ``` 1209 | 1210 | Unfortunately, that leaves a hole in the array. Arrays are objects, `indexes` ([1], [3]) are the `names` of the object. 1211 | 1212 | `array = {'0':'Peter', '1':'John'}` 1213 | 1214 | Names of the objects do not change after `delete` 1215 | 1216 | Use `splice` for that. 1217 | 1218 | ```js 1219 | numbers.splice(2, 1); 1220 | // numbers is ['zero', 'one', 'shi', 'go'] 1221 | ``` 1222 | The second argument is the number of elements to delete. 1223 | 1224 | Any additional arguments get inserted into the array at that point. 1225 | 1226 | ## Enumeration 1227 | Since JavaScript’s arrays are really objects, the `for in` statement can be used to iterate over all of the properties of an array. 1228 | 1229 | Unfortunately, for in makes no guarantee about the order of the properties, 1230 | 1231 | Use `for` instead 1232 | ```js 1233 | for (var i = 0; i < myArray.length; i += 1) { 1234 | document.writeln(myArray[i]); 1235 | } 1236 | ``` 1237 | 1238 | ## Confusion 1239 | When the property names are small sequential integers, you should use an array. Otherwise, use an object. 1240 | 1241 | **NOTE:** `typeof` operator reports that the type of an array is 'object. 1242 | 1243 | Use: 1244 | ```js 1245 | var is_array = function (value) { 1246 | return Object.prototype.toString.apply(value) === '[object Array]'; 1247 | }; 1248 | ``` 1249 | ##Methods 1250 | JavaScript provides a set of methods for acting on arrays. 1251 | 1252 | Array.prototype can be augmented as well. 1253 | 1254 | Add the `reduce` method to arrays: 1255 | 1256 | ```js 1257 | Array.method('reduce', function (f, value) { 1258 | var i; 1259 | for (i = 0; i < this.length; i += 1) { 1260 | value = f(this[i], value); 1261 | } 1262 | return value; 1263 | }); 1264 | ``` 1265 | 1266 | ```js 1267 | var data = [4, 8, 10]; 1268 | 1269 | var add = function (a, b) { 1270 | return a + b; 1271 | }; 1272 | 1273 | var sum = data.reduce(add, 0); // sum is 22 1274 | ``` 1275 | 1276 | We can also add methods directly to an individual array: 1277 | 1278 | ```js 1279 | data.total = function ( ) { 1280 | return this.reduce(add, 0); 1281 | }; 1282 | total = data.total( ); // total is 22 1283 | 1284 | ``` 1285 | 1286 | Since the string 'total' is not an integer, adding a total property to an array does not change its `length`. 1287 | 1288 | ## Dimensions 1289 | Add array initializers 1290 | 1291 | ```js 1292 | Array.dim = function (dimension, initial) { 1293 | var a = [], i; 1294 | for (i = 0; i < dimension; i += 1) { 1295 | a[i] = initial; 1296 | } 1297 | return a; 1298 | }; 1299 | // Make an array containing 10 zeros. 1300 | var myArray = Array.dim(10, 0); 1301 | ``` 1302 | 1303 | Add Matrix 1304 | 1305 | ```js 1306 | Array.matrix = function (m, n, initial) { 1307 | var a, i, j, mat = []; 1308 | 1309 | for (i = 0; i < m; i += 1) { 1310 | a = []; 1311 | for (j = 0; j < n; j += 1) { 1312 | a[j] = initial; 1313 | } 1314 | mat[i] = a; 1315 | } 1316 | 1317 | return mat; 1318 | }; 1319 | 1320 | // Make a 4 * 4 matrix filled with zeros. 1321 | var myMatrix = Array.matrix(4, 4, 0); 1322 | ``` 1323 | 1324 | #8. Methods 1325 | 1326 | ## Array 1327 | ### `array.concat(item…)` 1328 | The concat method produces a **NEW** array containing a shallow copy of this array with the items appended to it. 1329 | ```js 1330 | var a = ['a', 'b', 'c']; 1331 | var b = ['x', 'y', 'z']; 1332 | var c = a.concat(b, true); 1333 | // c is ['a', 'b', 'c', 'x', 'y', 'z', true] 1334 | ``` 1335 | 1336 | ### `array.join(separator)` 1337 | The join method makes a string from an array. 1338 | ```js 1339 | var a = ['a', 'b', 'c']; 1340 | a.push('d'); 1341 | var c = a.join(''); // c is 'abcd'; 1342 | ``` 1343 | 1344 | ### `array.pop( )` 1345 | The pop and push methods make an array work like a stack. 1346 | ```js 1347 | var a = ['a', 'b', 'c']; 1348 | var c = a.pop( ); // a is ['a', 'b'] & c is 'c' 1349 | ``` 1350 | 1351 | ### `array.push(item…)` 1352 | The push method appends items to the end of an array. Unlike the concat method, it **modifies** 1353 | the array and appends array items whole. It returns the new length: 1354 | 1355 | ```js 1356 | var a = ['a', 'b', 'c']; 1357 | var b = ['x', 'y', 'z']; 1358 | var c = a.push(b, true); 1359 | // a is ['a', 'b', 'c', ['x', 'y', 'z'], true] 1360 | // c is 5; 1361 | ``` 1362 | 1363 | ### `array.reverse( )` 1364 | The reverse method modifies the array by reversing the order of the elements. 1365 | 1366 | It returns the array 1367 | 1368 | ```js 1369 | var a = ['a', 'b', 'c']; 1370 | var b = a.reverse( ); 1371 | // both a and b are ['c', 'b', 'a'] 1372 | ``` 1373 | 1374 | ### `array.shift( )` 1375 | The shift method removes the first element from an array and returns it. 1376 | Usually Slower than pop 1377 | 1378 | ```js 1379 | var a = ['a', 'b', 'c']; 1380 | var c = a.shift( ); // a is ['b', 'c'] & c is 'a' 1381 | ``` 1382 | 1383 | ### `array.slice(start, end)` 1384 | The slice method makes a shallow copy of a portion of an array. 1385 | ```js 1386 | var a = ['a', 'b', 'c']; 1387 | var b = a.slice(0, 1); // b is ['a'] 1388 | var c = a.slice(1); // c is ['b', 'c'] 1389 | var d = a.slice(1, 2); // d is ['b'] 1390 | ``` 1391 | ### `array.sort(comparefn)` 1392 | The sort method sorts the contents of an array in place. 1393 | 1394 | It sorts arrays of numbers incorrectly: 1395 | ```js 1396 | var n = [4, 8, 15, 16, 23, 42]; 1397 | n.sort( ); 1398 | // n is [15, 16, 23, 4, 42, 8] 1399 | ``` 1400 | You may replace the comparison function with your own. 1401 | 1402 | Your comparison function should take two parameters and return 0 if the two parameters are equal, a negative number if the first parameter should come first, and a positive number if the second parameter should come first. 1403 | 1404 | ```js 1405 | n.sort(function (a, b) { 1406 | return a - b; 1407 | }); 1408 | // n is [4, 8, 15, 16, 23, 42]; 1409 | ``` 1410 | 1411 | ### `array.splice(start, deleteCount, item…)` 1412 | 1413 | The splice method removes elements from an array, replacing them with new items. 1414 | 1415 | ```js 1416 | var a = ['a', 'b', 'c']; 1417 | var r = a.splice(1, 1, 'ache', 'bug'); 1418 | // a is ['a', 'ache', 'bug', 'c'] 1419 | // r is ['b'] 1420 | ``` 1421 | 1422 | ### `array.unshift(item…)` 1423 | The unshift method is like the push method except that it shoves the items onto the front of this array instead of at the end. 1424 | 1425 | It returns the array’s new length: 1426 | 1427 | ```js 1428 | var a = ['a', 'b', 'c']; 1429 | var r = a.unshift('?', '@'); 1430 | // a is ['?', '@', 'a', 'b', 'c'] 1431 | // r is 5 1432 | ``` 1433 | 1434 | ## Function 1435 | ### `function.apply(thisArg, argArray)` 1436 | The apply method invokes a function, passing in the object that will be bound to this and an optional array of arguments. 1437 | 1438 | The apply method is used in the [The Apply Invocation Pattern](#the-apply-invocation-pattern) 1439 | 1440 | ## Number 1441 | ### `number.toExponential(fractionDigits)` 1442 | The `toExponential` method converts this number to a string in the exponential form. 1443 | 1444 | The optional fractionDigits parameter controls the number of decimal places. 1445 | 1446 | It should be between 0 and 20: 1447 | 1448 | ```js 1449 | document.writeln(Math.PI.toExponential(0)); // 3e+0 1450 | document.writeln(Math.PI.toExponential(2)); // 3.14e+0 1451 | document.writeln(Math.PI.toExponential(7)); // 3.1415927e+0 1452 | document.writeln(Math.PI.toExponential(16)); // 3.1415926535897930e+0 1453 | document.writeln(Math.PI.toExponential( )); // 3.141592653589793e+0 1454 | ``` 1455 | 1456 | ### `number.toFixed(fractionDigits)` 1457 | The `toFixed` method converts this number to a string in the decimal form. 1458 | 1459 | The optional fractionDigits parameter controls the number of decimal places. 1460 | 1461 | It should be between 0 and 20. The default is 0: 1462 | ```js 1463 | document.writeln(Math.PI.toFixed(0)); // 3 1464 | document.writeln(Math.PI.toFixed(2)); // 3.14 1465 | document.writeln(Math.PI.toFixed(7)); // 3.1415927 1466 | document.writeln(Math.PI.toFixed(16)); // 3.1415926535897930 1467 | document.writeln(Math.PI.toFixed( )); // 3 1468 | ``` 1469 | ### `number.toPrecision(precision)` 1470 | The `toPrecision` method converts this number to a string in the decimal form. 1471 | 1472 | The optional precision parameter controls the number of digits of precision. 1473 | 1474 | It should be between 1 and 21: 1475 | ```js 1476 | document.writeln(Math.PI.toPrecision(2)); // 3.1 1477 | document.writeln(Math.PI.toPrecision(7)); // 3.141593 1478 | document.writeln(Math.PI.toPrecision(16)); // 3.141592653589793 1479 | document.writeln(Math.PI.toPrecision( )); // 3.141592653589793 1480 | ``` 1481 | 1482 | ### `number.toString(radix)` 1483 | The `toString` method converts this number to a string. 1484 | 1485 | The optional radix parameter controls radix, or base. 1486 | 1487 | It should be between 2 and 36. 1488 | 1489 | The default radix is base 10. 1490 | 1491 | The radix parameter is most commonly used with integers, but it can be used on any number. 1492 | 1493 | ```js 1494 | document.writeln(Math.PI.toString(2)); // 11.001001000011111101101010100010001000010110100011 1495 | document.writeln(Math.PI.toString(8)); // 3.1103755242102643 1496 | document.writeln(Math.PI.toString(16)); // 3.243f6a8885a3 1497 | document.writeln(Math.PI.toString( )); // 3.141592653589793 1498 | ``` 1499 | 1500 | ## Object 1501 | ### `object.hasOwnProperty(name)` 1502 | The `hasOwnProperty` method returns true if the object contains a property having the name. 1503 | 1504 | The prototype chain is not examined. 1505 | 1506 | This method is useless if the name is hasOwnProperty 1507 | 1508 | ```js 1509 | var a = {member: true}; 1510 | var b = Object.create(a); // from Chapter 3 1511 | var t = a.hasOwnProperty('member'); // t is true 1512 | var u = b.hasOwnProperty('member'); // u is false 1513 | var v = b.member; // v is true 1514 | ``` 1515 | 1516 | ## RegExp 1517 | ### `regexp.exec(string)` 1518 | The exec method is the most powerful (and slowest) of the methods that use regular expressions. 1519 | 1520 | If it successfully matches the regexp and the string, it returns an array. 1521 | 1522 | The 0 element of the array will contain the substring that matched the regexp. 1523 | 1524 | The 1 element is the text captured by group 1, the 2 element is the text captured by group 2, and so on. 1525 | 1526 | If the match fails, it returns null. 1527 | 1528 | ### ```regexp.test(string)``` 1529 | The test method is the simplest (and fastest) of the methods that use regular expressions. 1530 | 1531 | If the regexp matches the string, it returns true; otherwise, it returns false. 1532 | 1533 | Do not use the `g` flag with this method: 1534 | 1535 | ```js 1536 | var b = /&.+;/.test('frank & beans'); 1537 | // b is true 1538 | ``` 1539 | ## String 1540 | ### `string.charAt(pos)` 1541 | The `charAt` method returns the character at position pos in this string. 1542 | 1543 | If pos is less than zero or greater than or equal to `string.length`, it returns the empty string. 1544 | 1545 | ```js 1546 | var name = 'Curly'; 1547 | var initial = name.charAt(0); // initial is 'C' 1548 | ``` 1549 | 1550 | ### `string.charCodeAt(pos)` 1551 | The `charCodeAt` method is the same as `charAt` except that instead of returning a string, it returns an integer representation of the code point value of the character at position `pos` in 1552 | that string. 1553 | 1554 | If `pos` is less than zero or greater than or equal to `string.length`, it returns NaN 1555 | 1556 | ```js 1557 | var name = 'Curly'; 1558 | var initial = name.charCodeAt(0); // initial is 67 1559 | ``` 1560 | ### `string.concat(string…)` 1561 | The `concat` method makes a new string by concatenating other strings together. 1562 | 1563 | It is rarely used because the + operator is more convenient: 1564 | ```js 1565 | var s = 'C'.concat('a', 't'); // s is 'Cat' 1566 | ``` 1567 | 1568 | ### `string.indexOf(searchString, position)` 1569 | The `indexOf` method searches for a searchString within a string. 1570 | 1571 | If it is found, it returns the position of the first matched character;otherwise, it returns –1. 1572 | 1573 | The optional position parameter causes the search to begin at some specified position in the `string` 1574 | 1575 | ```js 1576 | var text = 'Mississippi'; 1577 | var p = text.indexOf('ss'); // p is 2 1578 | p = text.indexOf('ss', 3); // p is 5 1579 | p = text.indexOf('ss', 6); // p is -1 1580 | ``` 1581 | ### `string.lastIndexOf(searchString, position)` 1582 | The `lastIndexOf` method is like the `indexOf` method, except that it searches from the end of the string instead of the front: 1583 | 1584 | ```js 1585 | var text = 'Mississippi'; 1586 | var p = text.lastIndexOf('ss'); // p is 5 1587 | p = text.lastIndexOf('ss', 3); // p is 2 1588 | p = text.lastIndexOf('ss', 6); // p is 5 1589 | ``` 1590 | 1591 | ### `string.localeCompare(that)` 1592 | The `localCompare` method compares two strings. 1593 | 1594 | The rules for how the strings are compared are not specified. 1595 | 1596 | If this string is less than that string, the result is negative. 1597 | 1598 | If they are equal, the result is zero. 1599 | 1600 | This is similar to the convention for the `array.sort` comparison function: 1601 | ```js 1602 | var m = ['AAA', 'A', 'aa', 'a', 'Aa', 'aaa']; 1603 | m.sort(function (a, b) { 1604 | return a.localeCompare(b); 1605 | }); 1606 | // m (in some locale) is 1607 | // ['a', 'A', 'aa', 'Aa', 'aaa', 'AAA'] 1608 | ``` 1609 | ### `string.match(regexp)` 1610 | The match method matches a string and a regular expression. 1611 | 1612 | How it does this depends on the `g` flag. 1613 | 1614 | If there is no g flag, then the result of calling `string.match(regexp)` is the same as calling `regexp.exec(string)`. 1615 | 1616 | However, if the regexp has the `g` flag, then it produces an array of all the matches but excludes the capturing groups. 1617 | 1618 | ```js 1619 | var text = '

' + 1620 | 'This is bold<\/b>!<\/p><\/body><\/html>'; 1621 | var tags = /[^<>]+|<(\/?)([A-Za-z]+)([^<>]*)>/g; 1622 | var a, i; 1623 | a = text.match(tags); 1624 | for (i = 0; i < a.length; i += 1) { 1625 | document.writeln(('// [' + i + '] ' + a[i]).entityify( )); 1626 | } 1627 | // The result is 1628 | // [0] 1629 | // [1] 1630 | // [2]

1631 | // [3] This is 1632 | // [4] 1633 | // [5] bold 1634 | // [6] 1635 | // [7] ! 1636 | // [8]

1637 | // [9] 1638 | // [10] 1639 | ``` 1640 | 1641 | ### `string.replace(searchValue,replaceValue)` 1642 | The `replace` method does a search and replace operation on this string, producing a new string. 1643 | 1644 | The searchValue argument can be a string or a regular expression object. 1645 | 1646 | If it is a string, only the first occurrence of the searchValue is replaced 1647 | 1648 | ```js 1649 | var result = "mother_in_law".replace('_', '-'); 1650 | ``` 1651 | will produce "mother-in_law", which might be a disappointment. 1652 | 1653 | If searchValue is a regular expression and if it has the `g` flag, then it will replace all occurrences. 1654 | 1655 | If it does not have the `g` flag, then it will replace only the first ccurrence. 1656 | 1657 | The replaceValue can be a string or a function. 1658 | 1659 | |Dollar sequence | Replacement | 1660 | |----------------|----------------------------| 1661 | | $$ | $ | 1662 | | $& | The matched text | 1663 | | $ number | Capture group text | 1664 | | $` |The text preceding the match| 1665 | | $' |The text following the match| 1666 | 1667 | If the replaceValue is a function, it will be called for each match, and the string returned by the function will be used as the replacement text. 1668 | 1669 | The first parameter passed to the function is the matched text. 1670 | 1671 | ### `string.search(regexp)` 1672 | The `search` method is like the indexOf method, except that it takes a regular expression object instead of a string. 1673 | 1674 | The g flag is ignored. 1675 | ```js 1676 | var text = 'and in it he says "Any damn fool could'; 1677 | var pos = text.search(/["']/); // pos is 18 1678 | ``` 1679 | ### `string.slice(start, end)` 1680 | The `slice` method makes a new string by copying a portion of another string. 1681 | 1682 | If the start parameter is negative, it adds `string.length` to it. 1683 | 1684 | The end parameter is optional, and its default value is `string.length`. 1685 | 1686 | If the end parameter is negative, then string.length is added to it. 1687 | 1688 | The end parameter is one greater than the position of the last character. 1689 | 1690 | ```js 1691 | var text = 'and in it he says "Any damn fool could'; 1692 | var a = text.slice(18); 1693 | // a is '"Any damn fool could' 1694 | var b = text.slice(0, 3); 1695 | // b is 'and' 1696 | var c = text.slice(-5); 1697 | // c is 'could' 1698 | var d = text.slice(19, 32); 1699 | // d is 'Any damn fool' 1700 | ``` 1701 | ### `string.split(separator, limit)` 1702 | The `split` method creates an array of strings by splitting this string into pieces. 1703 | 1704 | The optional limit parameter can limit the number of pieces that will be split. 1705 | 1706 | The separator parameter can be a string or a regular expression. 1707 | 1708 | If the separator is the empty string, an array of single characters is produced: 1709 | ```js 1710 | var digits = '0123456789'; 1711 | var a = digits.split('', 5); 1712 | // a is ['0', '1', '2', '3', '456789'] 1713 | ``` 1714 | Otherwise, the string is searched for all occurrences of the separator. 1715 | 1716 | Each unit of text between the separators is copied into the array. 1717 | 1718 | The `g` flag is ignored: 1719 | 1720 | ```js 1721 | var ip = '192.168.1.0'; 1722 | var b = ip.split('.'); 1723 | // b is ['192', '168', '1', '0'] 1724 | var c = '|a|b|c|'.split('|'); 1725 | // c is ['', 'a', 'b', 'c', ''] 1726 | ``` 1727 | 1728 | ### `string.substring(start, end)` 1729 | The `substring` method is the same as the slice method except that it doesn’t handle the 1730 | adjustment for negative parameters. 1731 | 1732 | There is no reason to use the substring method. Use slice instead. 1733 | 1734 | ### `string.toLocaleLowerCase( )` 1735 | 1736 | The `toLocaleLowerCase` method produces a new string that is made by converting this 1737 | string to lowercase using the rules for the locale. 1738 | 1739 | This is primarily for the benefit of Turkish because in that language ‘I’ converts to ı, not ‘i’. 1740 | 1741 | ### `string.toLocaleUpperCase( )` 1742 | The `toLocaleUpperCase` method produces a new string that is made by converting this 1743 | string to uppercase using the rules for the locale. 1744 | 1745 | This is primarily for the benefit of Turkish, because in that language ‘i’ converts to ‘ ’, not ‘I’. 1746 | 1747 | ### `string.toLowerCase( )` 1748 | The `toLowerCase` method produces a new string that is made by converting this string to 1749 | lowercase. 1750 | 1751 | ### `string.toUpperCase( )` 1752 | The `toUpperCase` method produces a new string that is made by converting this string to 1753 | uppercase. 1754 | ### `String.fromCharCode(char…)` 1755 | 1756 | The `String.fromCharCode` function produces a string from a series of numbers. 1757 | ```js 1758 | var a = String.fromCharCode(67, 97, 116); 1759 | // a is 'Cat' 1760 | ``` 1761 | 1762 | # Awful Parts 1763 | ## Global Variables 1764 | A global variable is a variable that is visible in every scope. 1765 | 1766 | Because a global variable can be changed by any part of the program at any time, they can significantly complicate the behavior of the program. 1767 | 1768 | There are three ways to define global variables. 1769 | 1770 | 1. Place a var statement outside of any function: 1771 | ```js 1772 | var foo = value; 1773 | ``` 1774 | 1775 | 2. Add a property directly to the global object. ie: 1776 | ```js 1777 | window.foo = value; 1778 | ``` 1779 | 1780 | 3. Use a variable without declaring it. 1781 | ```js 1782 | foo = value; 1783 | ``` 1784 | JavaScript’s policy of making forgotten variables global creates bugs that can be very difficult to find. 1785 | 1786 | ## Scope 1787 | JavaScript uses the block syntax, but does not provide block scope: 1788 | 1789 | _A variable declared in a block is visible everywhere in the function containing the block._ 1790 | 1791 | Best practice is to declare all variables at the top of each function. 1792 | 1793 | ## Semicolon Insertion 1794 | JavaScript has a mechanism that tries to correct faulty programs by automatically inserting semicolons. 1795 | 1796 | Do not depend on this. It can mask more serious errors. 1797 | 1798 | ```js 1799 | return 1800 | { 1801 | status: true 1802 | }; 1803 | // returns undefined 1804 | ``` 1805 | 1806 | ```js 1807 | return { 1808 | status: true 1809 | }; 1810 | //returns an object 1811 | ``` 1812 | 1813 | ## Reserved Words 1814 | The following words are reserved in JavaScript: 1815 | 1816 | `abstract boolean break byte case catch char class const continue debugger default 1817 | delete do double else enum export extends false final finally float for function goto 1818 | if implements import in instanceof int interface long native new null package private 1819 | protected public return short static super switch synchronized this throw throws 1820 | transient true try typeof var volatile void while with` 1821 | 1822 | They cannot be used to name variables or parameters. 1823 | 1824 | When reserved words are used as keys in object literals, they must be quoted. 1825 | 1826 | They cannot be used with the dot notation, so it is sometimes necessary to use the bracket notation instead. 1827 | 1828 | ```js 1829 | var method; // ok 1830 | var class; // illegal 1831 | object = {box: value}; // ok 1832 | object = {case: value}; // illegal 1833 | object = {'case': value}; // ok 1834 | object.box = value; // ok 1835 | object.case = value; // illegal 1836 | object['case'] = value; // ok 1837 | ``` 1838 | 1839 | ## Unicode 1840 | JavaScript’s characters are 16 bits. That is enough to cover the original 65,536 (which is now known as the Basic Multilingual Plane). 1841 | 1842 | Each of the remaining million characters can be represented as a pair of characters. 1843 | 1844 | Unicode considers the pair to be a single character. 1845 | 1846 | JavaScript thinks the pair is two distinct characters. 1847 | 1848 | ## typeof 1849 | ```js 1850 | typeof null 1851 | ``` 1852 | returns `object` 1853 | 1854 | You can fix it with: 1855 | ```js 1856 | if (my_value && typeof my_value === 'object') { 1857 | // my_value is an object or an array! 1858 | } 1859 | ``` 1860 | 1861 | Some implementations report that: 1862 | ```js 1863 | typeof /a/ 1864 | ``` 1865 | is `object`, and others say that it is `function`. 1866 | 1867 | ## parseInt 1868 | `parseInt` is a function that converts a string into an integer. 1869 | 1870 | `parseInt("16")` and `parseInt("16 tons")` produce the same result. 1871 | 1872 | If the first character of the string is 0, then the string is evaluated in base 8 instead of 1873 | base 10. 1874 | 1875 | `parseInt("08")` and `parseInt("09")` produce 0 as their result. 1876 | 1877 | Fortunately, `parseInt` can take a `radix` parameter, so that `parseInt("08",10)` produces 8. 1878 | 1879 | Use always the **radix** 1880 | 1881 | ## + 1882 | The + operator can add or concatenate. 1883 | 1884 | Which one it does depends on the types of the parameters. 1885 | 1886 | If either operand is an empty string, it produces the other operand 1887 | converted to a string. 1888 | 1889 | If both operands are numbers, it produces the sum. 1890 | 1891 | Otherwise, it converts both operands to strings and concatenates them. 1892 | 1893 | 1894 | ## Floating Point 1895 | Binary floating-point numbers are inept at handling decimal fractions, so 0.1 + 0.2 is not equal to 0.3. 1896 | 1897 | Use Integer aritmetic. ie: 1.05$ = 105/100 $ 1898 | 1899 | ## NaN 1900 | The value NaN is a special quantity defined by IEEE 754. It stands for not a number, even though: 1901 | ```js 1902 | typeof NaN === 'number' // true 1903 | ``` 1904 | The value can be produced by attempting to convert a string to a number when the string is not in the form of a number. For example: 1905 | ```js 1906 | + '0' // 0 1907 | + 'oops' // NaN 1908 | ``` 1909 | 1910 | `NaN` is not equal to itself. 1911 | ```js 1912 | NaN === NaN // false 1913 | NaN !== NaN // true 1914 | ``` 1915 | `isNaN` function that can distinguish between numbers and `NaN`: 1916 | ```js 1917 | isNaN(NaN) // true 1918 | isNaN(0) // false 1919 | isNaN('oops') // true 1920 | isNaN('0') // false 1921 | ``` 1922 | 1923 | You may want to define your own isNumber function: 1924 | ```js 1925 | var isNumber = function isNumber(value) { 1926 | return typeof value === 'number' && isFinite(value); 1927 | } 1928 | ``` 1929 | ## Phony Arrays 1930 | Javascript arrays can be considerably worse than real arrays 1931 | 1932 | The typeof operator does not distinguish between arrays and objects. You need 1933 | ```js 1934 | if (my_value && typeof my_value === 'object' && typeof my_value.length === 'number' && !(my_value.propertyIsEnumerable('length')) { 1935 | // my_value is truly an array! 1936 | } 1937 | ``` 1938 | In any case, the test can still fail if the propertyIsEnumerable method is overridden. 1939 | 1940 | ## Falsy Values 1941 | JavaScript has a surprisingly large set of falsy values 1942 | 1943 | |Value| Type | 1944 | | --- | ---- | 1945 | |0| Number| 1946 | |NaN (not a number)| Number| 1947 | |'' (empty string) |String| 1948 | |false| Boolean| 1949 | |null| Object| 1950 | |undefined| Undefined| 1951 | 1952 | ## `hasOwnProperty` 1953 | Unfortunately, `hasOwnProperty` is a method, not an operator, so in any object it could be replaced. 1954 | 1955 | ## Object 1956 | JavaScript’s objects are never truly empty because they can pick up members from the prototype chain. 1957 | 1958 | And sometimes that matters. 1959 | 1960 | # Bad Parts 1961 | ## == 1962 | Use always `===` and `!==` instead. 1963 | 1964 | ```js 1965 | '' == '0' // false 1966 | 0 == '' // true 1967 | 0 == '0' // true 1968 | false == 'false' // false 1969 | false == '0' // true 1970 | false == undefined // false 1971 | false == null // false 1972 | null == undefined // true 1973 | ' \t\r\n ' == 0 // true 1974 | ``` 1975 | 1976 | ## `with` Statement 1977 | the `with` statement was intended to provide a shorthand when 1978 | accessing the properties of an object. 1979 | 1980 | Unfortunately, its results can sometimes be unpredictable, so it should be avoided. 1981 | 1982 | ## `eval` 1983 | The eval function passes a string to the JavaScript compiler and executes the result. 1984 | 1985 | Should be avoided as `setInterval`, `setTimeout` and the Function constructor 1986 | 1987 | ## `continue` Statement 1988 | The continue statement jumps to the top of the loop. 1989 | 1990 | ## `switch` Fall Through 1991 | The switch statement was modeled after the FORTRAN IV computed go to statement. 1992 | 1993 | Each case falls through into the next case unless you explicitly disrupt the flow 1994 | 1995 | ## Block-less Statements 1996 | An if or while or do or for statement can take a block or a single statement. 1997 | 1998 | ```js 1999 | if (ok) 2000 | t = true; 2001 | //can become: 2002 | if (ok) 2003 | t = true; 2004 | advance( ); 2005 | //which looks like: 2006 | if (ok) { 2007 | t = true; 2008 | advance( ); 2009 | } 2010 | //but which actually means: 2011 | if (ok) { 2012 | t = true; 2013 | } 2014 | advance( ); 2015 | ``` 2016 | 2017 | ## `++` `--` 2018 | When `++` and `--` are used , the code tended to be too 2019 | tight, too tricky, too cryptic. 2020 | 2021 | Don’t use them 2022 | 2023 | ## Bitwise Operators 2024 | JavaScript has the same set of bitwise operators as Java: 2025 | ```js 2026 | & and 2027 | | or 2028 | ^ xor 2029 | ~ not 2030 | >> signed right shift 2031 | >>> unsigned right shift 2032 | << left shift 2033 | ``` 2034 | Bitwise operators convert their number operands into integers, do their business, and then convert them back. 2035 | 2036 | They are slow 2037 | 2038 | ## The function Statement Versus the function Expression 2039 | The statement: 2040 | ```js 2041 | function foo( ) {} 2042 | ``` 2043 | means about the same thing as: 2044 | ```js 2045 | var foo = function foo( ) {}; 2046 | ``` 2047 | 2048 | `function` statements are subject to _hoisting_. This means that regardless of where a `function` is placed, it is moved to the top of the scope in which it is defined. 2049 | 2050 | The first thing in a statement cannot be a function expression because the official grammar assumes that a statement that starts with the word function is a function statement. 2051 | 2052 | The workaround is to wrap the function expression in parentheses: 2053 | ```js 2054 | (function ( ) { 2055 | var hidden_variable; 2056 | // This function can have some impact on 2057 | // the environment, but introduces no new 2058 | // global variables. 2059 | })(); 2060 | ``` 2061 | 2062 | ## Typed Wrappers 2063 | JavaScript has a set of typed wrappers. For example: 2064 | 2065 | ```js 2066 | new Boolean(false) 2067 | ``` 2068 | 2069 | Don’t use `new Boolean` or `new Number` or `new String`. 2070 | 2071 | Also avoid `new Object` and `new Array`. Use `{}` and `[]` instead 2072 | 2073 | `new` 2074 | JavaScript’s new operator creates a new object that inherits from the operand’s prototype 2075 | member, and then calls the operand, binding the new object to this. This gives 2076 | the operand (which had better be a constructor function) a chance to customize the 2077 | new object before it is returned to the requestor. 2078 | 2079 | If youforget to use the new operator, youinstead get an ordinary function call, and 2080 | this is bound to the global object instead of to a new object. That means that your 2081 | function will be clobbering global variables when it attempts to initialize the new 2082 | members. 2083 | 2084 | Not use `new` at all. 2085 | 2086 | ## `void` 2087 | `void` is an operator that takes an operand and returns `undefined`. 2088 | 2089 | This is not useful, and it is very confusing. 2090 | 2091 | Avoid void. 2092 | 2093 | # JSLint 2094 | ## Undefined Variables and Functions 2095 | JSLint expects that all variables and functions will be declared before they are used or invoked. This allows it to detect implied global variables. 2096 | 2097 | ## Members 2098 | Since JavaScript is a loosely typed dynamic-object language, it is not possible to determine at compile time if property names are spelled correctly. 2099 | 2100 | JSLint provides some assistance with this. 2101 | 2102 | At the bottom of its report, JSLint displays a `/*members*/` comment. It contains all of the names and string literals that were used with dot notation, subscript notation, and object literals to name the members of objects. 2103 | 2104 | ## Options 2105 | | Option | Meaning | 2106 | | -- | -- | 2107 | |adsafe| true if ADsafe.org rules should be enforced| 2108 | |bitwise| true if bitwise operators should not be allowed| 2109 | |browser| true if the standard browser globals should be predefined| 2110 | |cap| true if uppercase HTML should be allowed| 2111 | |debug| true if debugger statements should be allowed| 2112 | |eqeqeq| true if === should be required| 2113 | |evil| true if eval should be allowed| 2114 | |forin| true if unfiltered for in statements should be allowed| 2115 | |fragment| true if HTML fragments should be allowed| 2116 | |glovar| true if var should not be allowed to declare global variables| 2117 | |laxbreak| true if statement breaks should not be checked| 2118 | |nomen| true if names should be checked| 2119 | |on| true if HTML event handlers should be allowed| 2120 | |passfail| true if the scan should stop on first error| 2121 | |plusplus| true if ++ and -- should not be allowed| 2122 | |rhino| true if the Rhino environment globals should be predefined| 2123 | |undef| true if undefined global variables are errors| 2124 | |white| true if strict whitespace rules apply| 2125 | |widget| true if the Yahoo! Widgets globals should be predefined| 2126 | 2127 | ## Semicolon 2128 | JSLint expects that every statement be followed by ; except for `for`, `function`, `if`, `switch`, `try`, and `while`. 2129 | 2130 | ## Line Breaking 2131 | JSLint expects long statements to be broken only after one of these punctuation characters or operators: 2132 | 2133 | `, . ; : { } ( [ = < > ? ! + - * / % ~ ^ | & 2134 | == != <= >= += -= *= /= %= ^=` 2135 | 2136 | ## Comma 2137 | JSLint expects to see the comma used as a separator, but not as an operator 2138 | 2139 | ## Required Blocks 2140 | JSLint expects that if and for statements will be made with blocks—that is, with statements enclosed in braces ({}). 2141 | 2142 | ## Forbidden Blocks 2143 | JSLint expects blocks with function, if, switch, while, for, do, and try statements and nowhere else. 2144 | 2145 | ## Expression Statements 2146 | An expression statement is expected to be an assignment, a function/method call, or delete. 2147 | 2148 | ## `for in` Statement 2149 | The body of every `for in` statement should be wrapped in an `if` statement that does filtering. 2150 | 2151 | ## `switch` Statement 2152 | JSLint expects that the statement before the next case or `default` is one of these: `break`, `return`, or `throw`. 2153 | 2154 | ## var Statement 2155 | JSLint expects that: 2156 | 2157 | * Avar will be declared only once, and that it will be declared before it is used. 2158 | * A function will be declared before it is used. 2159 | * Parameters will not also be declared as vars. 2160 | 2161 | JSLint does not expect: 2162 | 2163 | * The arguments array to be declared as a var. 2164 | * That a variable will be declared in a block. This is because JavaScript blocks do not have block scope. 2165 | 2166 | ## with Statement 2167 | Never use the with statement. Use a var instead. 2168 | 2169 | JSLint does not expect to see a with statement. 2170 | 2171 | ## `=` 2172 | JSLint does not expect to see an assignment statement in the condition part of an if or while statement. This is because it is more likely that: 2173 | ```js if (a = b) { 2174 | ... 2175 | } 2176 | ``` 2177 | Use 2178 | ```js 2179 | if ((a = b)) { 2180 | ... 2181 | } 2182 | ``` 2183 | ## `==` and `!=` 2184 | JSLint expects `===` or `!==` operators. 2185 | 2186 | ## Labels 2187 | JSLint expects labels only on statements that interact with `break`: `switch`, `while`, `do`, and `for`. 2188 | 2189 | JSLint expects that labels will be distinct from variables and parameters. 2190 | 2191 | ## Unreachable Code 2192 | JSLint expects that a `return`, `break`, `continue`, or `throw` statement will be followed by a `}` or `case` or `default`. 2193 | 2194 | ## Confusing Pluses and Minuses 2195 | JSLint expects that + will not be followed by + or ++, and that - will not be followed by - or --. 2196 | 2197 | ## ++ and -- 2198 | The JSLint option plusplus prohibits the use of these operators. 2199 | 2200 | ## Bitwise Operators 2201 | JSLint does not expect bitwise operators. 2202 | 2203 | ## `eval` Is Evil 2204 | JSLint does not expect evals. 2205 | 2206 | ## `void` 2207 | JSLint does not expect to see void because it is confusing 2208 | and not very useful. 2209 | 2210 | ## Regular Expressions 2211 | JSLint looks for problems 2212 | that may cause portability problems. It also attempts to resolve visual ambiguities by recommending explicit escapement. 2213 | JSLint expects that the character preceding a regular expression literal is a `(` or `=` or `:` or `,` character. 2214 | 2215 | ## Constructors and new 2216 | JSLint enforces the convention that constructor functions be given names with initial uppercase letters. 2217 | 2218 | JSLint does not expect to see a function invocation with an initial 2219 | uppercase name unless it has the new prefix. 2220 | 2221 | JSLint does not expect to see the new prefix used with functions whose names do not start with initial uppercase. 2222 | 2223 | JSLint does not expect to see the wrapper forms `new Number`, `new String`, or `new Boolean`. 2224 | 2225 | JSLint does not expect to see `new Object` (use `{}` instead). 2226 | 2227 | JSLint does not expect to see `new Array` (use `[]` instead). 2228 | 2229 | ## Not Looked For 2230 | JSLint does not chek if variables are assigned values before they are used. 2231 | 2232 | JSLint does not do any kind of global analysis. 2233 | 2234 | ## HTML 2235 | JSLint is able to handle HTML text. 2236 | 2237 | ## JSON 2238 | JSLint can also check that JSON data structures are well formed. 2239 | 2240 | ## Report 2241 | If JSLint is able to complete its scan, it generates a function report. It lists the following 2242 | for each function: 2243 | * The line number on which it starts. 2244 | * Its name. In the case of anonymous functions, JSLint will “guess” the name. 2245 | * The parameters. 2246 | * Closure: the variables and parameters that are declared in the function that are 2247 | used by its inner functions. 2248 | * Variables: the variables declared in the function that are used only by the function. 2249 | * Unused: the variables that are declared in the function that are not used. This 2250 | may be an indication of an error. 2251 | * Outer: variables used by this function that are declared in another function. 2252 | * Global: global variables that are used by this function. 2253 | * Label: statement labels that are used by this function. 2254 | 2255 | The report will also include a list of all of the member names that were used. 2256 | 2257 | # JSON 2258 | ## JSON syntax 2259 | JSON has six kinds of values: `objects`, `arrays`, `strings`, `numbers`, `booleans` (`true` and 2260 | `false`), and the special value `null`. 2261 | 2262 | Whitespace (spaces, tabs, carriage returns, and newline characters) may be inserted before or after any value. 2263 | 2264 | A JSON object is an unordered container of name/value pairs. 2265 | 2266 | A name can be any string. 2267 | 2268 | A value can be any JSON value, including arrays and objects. 2269 | 2270 | JSON objects can be nested to any depth 2271 | 2272 | The JSON array is an ordered sequence of values. 2273 | 2274 | A value can be any JSON value, including `arrays` and `objects`. 2275 | 2276 | ![alt text][json-value] 2277 | 2278 | ![alt text][json-object] 2279 | 2280 | ![alt text][json-array] 2281 | 2282 | 2283 | A JSON string is wrapped in double quotes. 2284 | 2285 | The `\` character is used for escapement. 2286 | 2287 | JSON allows the `/` character to be escaped so that JSON can be embedded in HTML `` tag. 2290 | 2291 | JSON allows `<\/`, which produces the same result but does not confuse HTML. 2292 | 2293 | JSON numbers are like JavaScript numbers. 2294 | 2295 | A leading zero is not allowed. 2296 | 2297 | A number can be an integer, real, or scientific. 2298 | 2299 | ![alt text][json-string] 2300 | 2301 | ![alt text][json-number] 2302 | 2303 | ## Using JSON Securely 2304 | Use the `JSON.parse` 2305 | 2306 | 2307 | [block]: http://cdn.oreilly.com/excerpts/9780596517748/web/jsgp_ad02.png 2308 | [break]: http://cdn.oreilly.com/excerpts/9780596517748/web/jsgp_ad03.png 2309 | [case]: http://cdn.oreilly.com/excerpts/9780596517748/web/jsgp_ad04.png 2310 | [disruptive]: http://cdn.oreilly.com/excerpts/9780596517748/web/jsgp_ad05.png 2311 | [do]: http://cdn.oreilly.com/excerpts/9780596517748/web/jsgp_ad06.png 2312 | [escaped]: http://cdn.oreilly.com/excerpts/9780596517748/web/jsgp_ad07.png 2313 | [exponent]: http://cdn.oreilly.com/excerpts/9780596517748/web/jsgp_ad08.png 2314 | [expression]:http://cdn.oreilly.com/excerpts/9780596517748/web/jsgp_ad09.png 2315 | [expression-statement]: http://cdn.oreilly.com/excerpts/9780596517748/web/jsgp_ad10.png 2316 | [function-body]: http://cdn.oreilly.com/excerpts/9780596517748/web/jsgp_ad13.png 2317 | [function-literal]: http://cdn.oreilly.com/excerpts/9780596517748/web/jsgp_ad14.png 2318 | [if]: http://cdn.oreilly.com/excerpts/9780596517748/web/jsgp_ad15.png 2319 | [infix]: http://cdn.oreilly.com/excerpts/9780596517748/web/jsgp_ad16.png 2320 | [invocation]: http://cdn.oreilly.com/excerpts/9780596517748/web/jsgp_ad18.png 2321 | [integer]: http://cdn.oreilly.com/excerpts/9780596517748/web/jsgp_ad17.png 2322 | [fraction]: http://cdn.oreilly.com/excerpts/9780596517748/web/jsgp_ad12.png 2323 | [for]: http://cdn.oreilly.com/excerpts/9780596517748/web/jsgp_ad11.png 2324 | [literal]: http://cdn.oreilly.com/excerpts/9780596517748/web/jsgp_ad19.png 2325 | [name]: http://cdn.oreilly.com/excerpts/9780596517748/web/jsgp_ad20.png 2326 | [numbers]: http://cdn.oreilly.com/excerpts/9780596517748/web/jsgp_ad21.png 2327 | [object-literal]: http://cdn.oreilly.com/excerpts/9780596517748/web/jsgp_ad22.png 2328 | [parameters]: http://cdn.oreilly.com/excerpts/9780596517748/web/jsgp_ad23.png 2329 | [prefix]:http://cdn.oreilly.com/excerpts/9780596517748/web/jsgp_ad24.png 2330 | [refinement]: http://cdn.oreilly.com/excerpts/9780596517748/web/jsgp_ad25.png 2331 | [regexp-literal]: http://cdn.oreilly.com/excerpts/9780596517748/web/jsgp_ad32.png 2332 | [return]: http://cdn.oreilly.com/excerpts/9780596517748/web/jsgp_ad35.png 2333 | [space]: http://cdn.oreilly.com/excerpts/9780596517748/web/jsgp_ad43.png 2334 | [string]: http://cdn.oreilly.com/excerpts/9780596517748/web/jsgp_ad37.png 2335 | [statements]: http://cdn.oreilly.com/excerpts/9780596517748/web/jsgp_ad36.png 2336 | [switch]: http://cdn.oreilly.com/excerpts/9780596517748/web/jsgp_ad38.png 2337 | [throw]: http://cdn.oreilly.com/excerpts/9780596517748/web/jsgp_ad39.png 2338 | [try]: http://cdn.oreilly.com/excerpts/9780596517748/web/jsgp_ad40.png 2339 | [var]: http://cdn.oreilly.com/excerpts/9780596517748/web/jsgp_ad41.png 2340 | [while]: http://cdn.oreilly.com/excerpts/9780596517748/web/jsgp_ad42.png 2341 | 2342 | [regexp1]: http://cdn.oreilly.com/excerpts/9780596517748/web/jsgp_ad26.png 2343 | [json-value]:http://cdn.oreilly.com/excerpts/9780596517748/web/jsgp_ae01.png 2344 | [json-object]:http://cdn.oreilly.com/excerpts/9780596517748/web/jsgp_ae02.png 2345 | [json-array]:http://cdn.oreilly.com/excerpts/9780596517748/web/jsgp_ae03.png 2346 | [json-string]:http://cdn.oreilly.com/excerpts/9780596517748/web/jsgp_ae04.png 2347 | [json-number]:http://cdn.oreilly.com/excerpts/9780596517748/web/jsgp_ae05.png --------------------------------------------------------------------------------