├── README.md ├── linters ├── SublimeLinter │ └── SublimeLinter.sublime-settings └── jshintrc └── package.json /README.md: -------------------------------------------------------------------------------- 1 | # Fullstack Academy's JavaScript Style Guide() { 2 | 3 | A mostly reasonable approach to JavaScript, *Adapted from AirBnB's popular JavaScript style guide*. 4 | 5 | 6 | ## Table of Contents 7 | 8 | 1. [Types](#types) 9 | 1. [Objects](#objects) 10 | 1. [Arrays](#arrays) 11 | 1. [Strings](#strings) 12 | 1. [Functions](#functions) 13 | 1. [Properties](#properties) 14 | 1. [Variables](#variables) 15 | 1. [Hoisting](#hoisting) 16 | 1. [Conditional Expressions & Equality](#conditional-expressions--equality) 17 | 1. [Blocks](#blocks) 18 | 1. [Comments](#comments) 19 | 1. [Whitespace](#whitespace) 20 | 1. [Commas](#commas) 21 | 1. [Semicolons](#semicolons) 22 | 1. [Type Casting & Coercion](#type-casting--coercion) 23 | 1. [Naming Conventions](#naming-conventions) 24 | 1. [Accessors](#accessors) 25 | 1. [Constructors](#constructors) 26 | 1. [Events](#events) 27 | 1. [Modules](#modules) 28 | 1. [jQuery](#jquery) 29 | 1. [ECMAScript 5 Compatibility](#ecmascript-5-compatibility) 30 | 1. [Testing](#testing) 31 | 1. [Performance](#performance) 32 | 1. [Resources](#resources) 33 | 1. [In the Wild](#in-the-wild) 34 | 1. [Translation](#translation) 35 | 1. [The JavaScript Style Guide Guide](#the-javascript-style-guide-guide) 36 | 1. [Contributors](#contributors) 37 | 1. [License](#license) 38 | 39 | ## Types 40 | 41 | - **Primitives**: When you access a primitive type you work directly on its value 42 | 43 | + `string` 44 | + `number` 45 | + `boolean` 46 | + `null` 47 | + `undefined` 48 | 49 | ```javascript 50 | var foo = 1, 51 | bar = foo; 52 | 53 | bar = 9; 54 | 55 | console.log(foo, bar); // => 1, 9 56 | ``` 57 | - **Complex**: When you access a complex type you work on a reference to its value 58 | 59 | + `object` 60 | + `array` 61 | + `function` 62 | 63 | ```javascript 64 | var foo = [1, 2], 65 | bar = foo; 66 | 67 | bar[0] = 9; 68 | 69 | console.log(foo[0], bar[0]); // => 9, 9 70 | ``` 71 | 72 | **[⬆ back to top](#table-of-contents)** 73 | 74 | ## Objects 75 | 76 | - Use the literal syntax for object creation. 77 | 78 | ```javascript 79 | // bad 80 | var item = new Object(); 81 | 82 | // good 83 | var item = {}; 84 | ``` 85 | 86 | - Don't use [reserved words](http://es5.github.io/#x7.6.1) as keys. It won't work in IE8. [More info](https://github.com/airbnb/javascript/issues/61) 87 | 88 | ```javascript 89 | // bad 90 | var superman = { 91 | default: { clark: 'kent' }, 92 | private: true 93 | }; 94 | 95 | // good 96 | var superman = { 97 | defaults: { clark: 'kent' }, 98 | hidden: true 99 | }; 100 | ``` 101 | 102 | - Use readable synonyms in place of reserved words. 103 | 104 | ```javascript 105 | // bad 106 | var superman = { 107 | class: 'alien' 108 | }; 109 | 110 | // bad 111 | var superman = { 112 | klass: 'alien' 113 | }; 114 | 115 | // good 116 | var superman = { 117 | type: 'alien' 118 | }; 119 | ``` 120 | 121 | **[⬆ back to top](#table-of-contents)** 122 | 123 | ## Arrays 124 | 125 | - Use the literal syntax for array creation 126 | 127 | ```javascript 128 | // bad 129 | var items = new Array(); 130 | 131 | // good 132 | var items = []; 133 | ``` 134 | 135 | - If you don't know array length use Array#push. 136 | 137 | ```javascript 138 | var someStack = []; 139 | 140 | 141 | // bad 142 | someStack[someStack.length] = 'abracadabra'; 143 | 144 | // good 145 | someStack.push('abracadabra'); 146 | ``` 147 | 148 | - When you need to copy an array use Array#slice. [jsPerf](http://jsperf.com/converting-arguments-to-an-array/7) 149 | 150 | ```javascript 151 | var len = items.length, 152 | itemsCopy = [], 153 | i; 154 | 155 | // bad 156 | for (i = 0; i < len; i++) { 157 | itemsCopy[i] = items[i]; 158 | } 159 | 160 | // good 161 | itemsCopy = items.slice(); 162 | ``` 163 | 164 | - To convert an array-like object to an array, use Array#slice. 165 | 166 | ```javascript 167 | function trigger() { 168 | var args = Array.prototype.slice.call(arguments); 169 | ... 170 | } 171 | ``` 172 | 173 | **[⬆ back to top](#table-of-contents)** 174 | 175 | 176 | ## Strings 177 | 178 | - Use single quotes `''` for strings 179 | 180 | ```javascript 181 | // bad 182 | var name = "Bob Parr"; 183 | 184 | // good 185 | var name = 'Bob Parr'; 186 | 187 | // bad 188 | var fullName = "Bob " + this.lastName; 189 | 190 | // good 191 | var fullName = 'Bob ' + this.lastName; 192 | ``` 193 | 194 | - Strings longer than 80 characters should be written across multiple lines using string concatenation. 195 | - Note: If overused, long strings with concatenation could impact performance. [jsPerf](http://jsperf.com/ya-string-concat) & [Discussion](https://github.com/airbnb/javascript/issues/40) 196 | 197 | ```javascript 198 | // bad 199 | var errorMessage = 'This is a super long error that was thrown because of Batman. When you stop to think about how Batman had anything to do with this, you would get nowhere fast.'; 200 | 201 | // bad 202 | var errorMessage = 'This is a super long error that was thrown because \ 203 | of Batman. When you stop to think about how Batman had anything to do \ 204 | with this, you would get nowhere \ 205 | fast.'; 206 | 207 | // good 208 | var errorMessage = 'This is a super long error that was thrown because ' + 209 | 'of Batman. When you stop to think about how Batman had anything to do ' + 210 | 'with this, you would get nowhere fast.'; 211 | ``` 212 | 213 | - When programmatically building up a string, use Array#join instead of string concatenation. Mostly for IE: [jsPerf](http://jsperf.com/string-vs-array-concat/2). 214 | 215 | ```javascript 216 | var items, 217 | messages, 218 | length, 219 | i; 220 | 221 | messages = [{ 222 | state: 'success', 223 | message: 'This one worked.' 224 | }, { 225 | state: 'success', 226 | message: 'This one worked as well.' 227 | }, { 228 | state: 'error', 229 | message: 'This one did not work.' 230 | }]; 231 | 232 | length = messages.length; 233 | 234 | // bad 235 | function inbox(messages) { 236 | items = ''; 243 | } 244 | 245 | // good 246 | function inbox(messages) { 247 | items = []; 248 | 249 | for (i = 0; i < length; i++) { 250 | items[i] = messages[i].message; 251 | } 252 | 253 | return ''; 254 | } 255 | ``` 256 | 257 | **[⬆ back to top](#table-of-contents)** 258 | 259 | 260 | ## Functions 261 | 262 | - Function expressions: 263 | 264 | ```javascript 265 | // anonymous function expression 266 | var anonymous = function() { 267 | return true; 268 | }; 269 | 270 | // named function expression 271 | var named = function named() { 272 | return true; 273 | }; 274 | 275 | // immediately-invoked function expression (IIFE) 276 | (function() { 277 | console.log('Welcome to the Internet. Please follow me.'); 278 | })(); 279 | ``` 280 | 281 | - Never declare a function in a non-function block (if, while, etc). Assign the function to a variable instead. Browsers will allow you to do it, but they all interpret it differently, which is bad news bears. 282 | - **Note:** ECMA-262 defines a `block` as a list of statements. A function declaration is not a statement. [Read ECMA-262's note on this issue](http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf#page=97). 283 | 284 | ```javascript 285 | // bad 286 | if (currentUser) { 287 | function test() { 288 | console.log('Nope.'); 289 | } 290 | } 291 | 292 | // good 293 | var test; 294 | if (currentUser) { 295 | test = function test() { 296 | console.log('Yup.'); 297 | }; 298 | } 299 | ``` 300 | 301 | - Never name a parameter `arguments`, this will take precedence over the `arguments` object that is given to every function scope. 302 | 303 | ```javascript 304 | // bad 305 | function nope(name, options, arguments) { 306 | // ...stuff... 307 | } 308 | 309 | // good 310 | function yup(name, options, args) { 311 | // ...stuff... 312 | } 313 | ``` 314 | 315 | **[⬆ back to top](#table-of-contents)** 316 | 317 | 318 | 319 | ## Properties 320 | 321 | - Use dot notation when accessing properties. 322 | 323 | ```javascript 324 | var luke = { 325 | jedi: true, 326 | age: 28 327 | }; 328 | 329 | // bad 330 | var isJedi = luke['jedi']; 331 | 332 | // good 333 | var isJedi = luke.jedi; 334 | ``` 335 | 336 | - Use subscript notation `[]` when accessing properties with a variable. 337 | 338 | ```javascript 339 | var luke = { 340 | jedi: true, 341 | age: 28 342 | }; 343 | 344 | function getProp(prop) { 345 | return luke[prop]; 346 | } 347 | 348 | var isJedi = getProp('jedi'); 349 | ``` 350 | 351 | **[⬆ back to top](#table-of-contents)** 352 | 353 | 354 | ## Variables 355 | 356 | - Always use `var` to declare variables. Not doing so will result in global variables. We want to avoid polluting the global namespace. Captain Planet warned us of that. 357 | 358 | ```javascript 359 | // bad 360 | superPower = new SuperPower(); 361 | 362 | // good 363 | var superPower = new SuperPower(); 364 | ``` 365 | 366 | - Use one `var` declaration for multiple variables and declare each variable on a newline. 367 | 368 | ```javascript 369 | // bad 370 | var items = getItems(); 371 | var goSportsTeam = true; 372 | var dragonball = 'z'; 373 | 374 | // good 375 | var items = getItems(), 376 | goSportsTeam = true, 377 | dragonball = 'z'; 378 | ``` 379 | 380 | - Declare unassigned variables last. This is helpful when later on you might need to assign a variable depending on one of the previous assigned variables. 381 | 382 | ```javascript 383 | // bad 384 | var i, len, dragonball, 385 | items = getItems(), 386 | goSportsTeam = true; 387 | 388 | // bad 389 | var i, items = getItems(), 390 | dragonball, 391 | goSportsTeam = true, 392 | len; 393 | 394 | // good 395 | var items = getItems(), 396 | goSportsTeam = true, 397 | dragonball, 398 | length, 399 | i; 400 | ``` 401 | 402 | - Assign variables at the top of their scope. This helps avoid issues with variable declaration and assignment hoisting related issues. 403 | 404 | ```javascript 405 | // bad 406 | function() { 407 | test(); 408 | console.log('doing stuff..'); 409 | 410 | //..other stuff.. 411 | 412 | var name = getName(); 413 | 414 | if (name === 'test') { 415 | return false; 416 | } 417 | 418 | return name; 419 | } 420 | 421 | // good 422 | function() { 423 | var name = getName(); 424 | 425 | test(); 426 | console.log('doing stuff..'); 427 | 428 | //..other stuff.. 429 | 430 | if (name === 'test') { 431 | return false; 432 | } 433 | 434 | return name; 435 | } 436 | 437 | // bad 438 | function() { 439 | var name = getName(); 440 | 441 | if (!arguments.length) { 442 | return false; 443 | } 444 | 445 | return true; 446 | } 447 | 448 | // good 449 | function() { 450 | if (!arguments.length) { 451 | return false; 452 | } 453 | 454 | var name = getName(); 455 | 456 | return true; 457 | } 458 | ``` 459 | 460 | **[⬆ back to top](#table-of-contents)** 461 | 462 | 463 | ## Hoisting 464 | 465 | - Variable declarations get hoisted to the top of their scope, their assignment does not. 466 | 467 | ```javascript 468 | // we know this wouldn't work (assuming there 469 | // is no notDefined global variable) 470 | function example() { 471 | console.log(notDefined); // => throws a ReferenceError 472 | } 473 | 474 | // creating a variable declaration after you 475 | // reference the variable will work due to 476 | // variable hoisting. Note: the assignment 477 | // value of `true` is not hoisted. 478 | function example() { 479 | console.log(declaredButNotAssigned); // => undefined 480 | var declaredButNotAssigned = true; 481 | } 482 | 483 | // The interpreter is hoisting the variable 484 | // declaration to the top of the scope. 485 | // Which means our example could be rewritten as: 486 | function example() { 487 | var declaredButNotAssigned; 488 | console.log(declaredButNotAssigned); // => undefined 489 | declaredButNotAssigned = true; 490 | } 491 | ``` 492 | 493 | - Anonymous function expressions hoist their variable name, but not the function assignment. 494 | 495 | ```javascript 496 | function example() { 497 | console.log(anonymous); // => undefined 498 | 499 | anonymous(); // => TypeError anonymous is not a function 500 | 501 | var anonymous = function() { 502 | console.log('anonymous function expression'); 503 | }; 504 | } 505 | ``` 506 | 507 | - Named function expressions hoist the variable name, not the function name or the function body. 508 | 509 | ```javascript 510 | function example() { 511 | console.log(named); // => undefined 512 | 513 | named(); // => TypeError named is not a function 514 | 515 | superPower(); // => ReferenceError superPower is not defined 516 | 517 | var named = function superPower() { 518 | console.log('Flying'); 519 | }; 520 | } 521 | 522 | // the same is true when the function name 523 | // is the same as the variable name. 524 | function example() { 525 | console.log(named); // => undefined 526 | 527 | named(); // => TypeError named is not a function 528 | 529 | var named = function named() { 530 | console.log('named'); 531 | } 532 | } 533 | ``` 534 | 535 | - Function declarations hoist their name and the function body. 536 | 537 | ```javascript 538 | function example() { 539 | superPower(); // => Flying 540 | 541 | function superPower() { 542 | console.log('Flying'); 543 | } 544 | } 545 | ``` 546 | 547 | - For more information refer to [JavaScript Scoping & Hoisting](http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting) by [Ben Cherry](http://www.adequatelygood.com/) 548 | 549 | **[⬆ back to top](#table-of-contents)** 550 | 551 | 552 | 553 | ## Conditional Expressions & Equality 554 | 555 | - Use `===` and `!==` over `==` and `!=`. 556 | - Conditional expressions are evaluated using coercion with the `ToBoolean` method and always follow these simple rules: 557 | 558 | + **Objects** evaluate to **true** 559 | + **Undefined** evaluates to **false** 560 | + **Null** evaluates to **false** 561 | + **Booleans** evaluate to **the value of the boolean** 562 | + **Numbers** evaluate to **false** if **+0, -0, or NaN**, otherwise **true** 563 | + **Strings** evaluate to **false** if an empty string `''`, otherwise **true** 564 | 565 | ```javascript 566 | if ([0]) { 567 | // true 568 | // An array is an object, objects evaluate to true 569 | } 570 | ``` 571 | 572 | - Use shortcuts. 573 | 574 | ```javascript 575 | // bad 576 | if (name !== '') { 577 | // ...stuff... 578 | } 579 | 580 | // good 581 | if (name) { 582 | // ...stuff... 583 | } 584 | 585 | // bad 586 | if (collection.length > 0) { 587 | // ...stuff... 588 | } 589 | 590 | // good 591 | if (collection.length) { 592 | // ...stuff... 593 | } 594 | ``` 595 | 596 | - For more information see [Truth Equality and JavaScript](http://javascriptweblog.wordpress.com/2011/02/07/truth-equality-and-javascript/#more-2108) by Angus Croll 597 | 598 | **[⬆ back to top](#table-of-contents)** 599 | 600 | 601 | ## Blocks 602 | 603 | - Use braces with all multi-line blocks. 604 | 605 | ```javascript 606 | // bad 607 | if (test) 608 | return false; 609 | 610 | // good 611 | if (test) return false; 612 | 613 | // good 614 | if (test) { 615 | return false; 616 | } 617 | 618 | // bad 619 | function() { return false; } 620 | 621 | // good 622 | function() { 623 | return false; 624 | } 625 | ``` 626 | 627 | **[⬆ back to top](#table-of-contents)** 628 | 629 | 630 | ## Comments 631 | 632 | - Use `/** ... */` for multiline comments. Include a description, specify types and values for all parameters and return values. 633 | 634 | ```javascript 635 | // bad 636 | // make() returns a new element 637 | // based on the passed in tag name 638 | // 639 | // @param tag 640 | // @return element 641 | function make(tag) { 642 | 643 | // ...stuff... 644 | 645 | return element; 646 | } 647 | 648 | // good 649 | /** 650 | * make() returns a new element 651 | * based on the passed in tag name 652 | * 653 | * @param tag 654 | * @return element 655 | */ 656 | function make(tag) { 657 | 658 | // ...stuff... 659 | 660 | return element; 661 | } 662 | ``` 663 | 664 | - Use `//` for single line comments. Place single line comments on a newline above the subject of the comment. Put an empty line before the comment. 665 | 666 | ```javascript 667 | // bad 668 | var active = true; // is current tab 669 | 670 | // good 671 | // is current tab 672 | var active = true; 673 | 674 | // bad 675 | function getType() { 676 | console.log('fetching type...'); 677 | // set the default type to 'no type' 678 | var type = this._type || 'no type'; 679 | 680 | return type; 681 | } 682 | 683 | // good 684 | function getType() { 685 | console.log('fetching type...'); 686 | 687 | // set the default type to 'no type' 688 | var type = this._type || 'no type'; 689 | 690 | return type; 691 | } 692 | ``` 693 | 694 | - Prefixing your comments with `FIXME` or `TODO` helps other developers quickly understand if you're pointing out a problem that needs to be revisited, or if you're suggesting a solution to the problem that needs to be implemented. These are different than regular comments because they are actionable. The actions are `FIXME -- need to figure this out` or `TODO -- need to implement`. 695 | 696 | - Use `// FIXME:` to annotate problems 697 | 698 | ```javascript 699 | function Calculator() { 700 | 701 | // FIXME: shouldn't use a global here 702 | total = 0; 703 | 704 | return this; 705 | } 706 | ``` 707 | 708 | - Use `// TODO:` to annotate solutions to problems 709 | 710 | ```javascript 711 | function Calculator() { 712 | 713 | // TODO: total should be configurable by an options param 714 | this.total = 0; 715 | 716 | return this; 717 | } 718 | ``` 719 | 720 | **[⬆ back to top](#table-of-contents)** 721 | 722 | 723 | ## Whitespace 724 | 725 | - Use soft tabs set to 2 spaces 726 | 727 | ```javascript 728 | // bad 729 | function() { 730 | ∙∙∙∙var name; 731 | } 732 | 733 | // bad 734 | function() { 735 | ∙var name; 736 | } 737 | 738 | // good 739 | function() { 740 | ∙∙var name; 741 | } 742 | ``` 743 | 744 | - Place 1 space before the leading brace. 745 | 746 | ```javascript 747 | // bad 748 | function test(){ 749 | console.log('test'); 750 | } 751 | 752 | // good 753 | function test() { 754 | console.log('test'); 755 | } 756 | 757 | // bad 758 | dog.set('attr',{ 759 | age: '1 year', 760 | breed: 'Bernese Mountain Dog' 761 | }); 762 | 763 | // good 764 | dog.set('attr', { 765 | age: '1 year', 766 | breed: 'Bernese Mountain Dog' 767 | }); 768 | ``` 769 | 770 | - Set off operators with spaces. 771 | 772 | ```javascript 773 | // bad 774 | var x=y+5; 775 | 776 | // good 777 | var x = y + 5; 778 | ``` 779 | 780 | - End files with a single newline character. 781 | 782 | ```javascript 783 | // bad 784 | (function(global) { 785 | // ...stuff... 786 | })(this); 787 | ``` 788 | 789 | ```javascript 790 | // bad 791 | (function(global) { 792 | // ...stuff... 793 | })(this);↵ 794 | ↵ 795 | ``` 796 | 797 | ```javascript 798 | // good 799 | (function(global) { 800 | // ...stuff... 801 | })(this);↵ 802 | ``` 803 | 804 | - Use indentation when making long method chains. 805 | 806 | ```javascript 807 | // bad 808 | $('#items').find('.selected').highlight().end().find('.open').updateCount(); 809 | 810 | // good 811 | $('#items') 812 | .find('.selected') 813 | .highlight() 814 | .end() 815 | .find('.open') 816 | .updateCount(); 817 | 818 | // bad 819 | var leds = stage.selectAll('.led').data(data).enter().append('svg:svg').class('led', true) 820 | .attr('width', (radius + margin) * 2).append('svg:g') 821 | .attr('transform', 'translate(' + (radius + margin) + ',' + (radius + margin) + ')') 822 | .call(tron.led); 823 | 824 | // good 825 | var leds = stage.selectAll('.led') 826 | .data(data) 827 | .enter().append('svg:svg') 828 | .class('led', true) 829 | .attr('width', (radius + margin) * 2) 830 | .append('svg:g') 831 | .attr('transform', 'translate(' + (radius + margin) + ',' + (radius + margin) + ')') 832 | .call(tron.led); 833 | ``` 834 | 835 | **[⬆ back to top](#table-of-contents)** 836 | 837 | ## Commas 838 | 839 | - Leading commas: **Nope.** 840 | 841 | ```javascript 842 | // bad 843 | var once 844 | , upon 845 | , aTime; 846 | 847 | // good 848 | var once, 849 | upon, 850 | aTime; 851 | 852 | // bad 853 | var hero = { 854 | firstName: 'Bob' 855 | , lastName: 'Parr' 856 | , heroName: 'Mr. Incredible' 857 | , superPower: 'strength' 858 | }; 859 | 860 | // good 861 | var hero = { 862 | firstName: 'Bob', 863 | lastName: 'Parr', 864 | heroName: 'Mr. Incredible', 865 | superPower: 'strength' 866 | }; 867 | ``` 868 | 869 | - Additional trailing comma: **Nope.** This can cause problems with IE6/7 and IE9 if it's in quirksmode. Also, in some implementations of ES3 would add length to an array if it had an additional trailing comma. This was clarified in ES5 ([source](http://es5.github.io/#D)): 870 | 871 | > Edition 5 clarifies the fact that a trailing comma at the end of an ArrayInitialiser does not add to the length of the array. This is not a semantic change from Edition 3 but some implementations may have previously misinterpreted this. 872 | 873 | ```javascript 874 | // bad 875 | var hero = { 876 | firstName: 'Kevin', 877 | lastName: 'Flynn', 878 | }; 879 | 880 | var heroes = [ 881 | 'Batman', 882 | 'Superman', 883 | ]; 884 | 885 | // good 886 | var hero = { 887 | firstName: 'Kevin', 888 | lastName: 'Flynn' 889 | }; 890 | 891 | var heroes = [ 892 | 'Batman', 893 | 'Superman' 894 | ]; 895 | ``` 896 | 897 | **[⬆ back to top](#table-of-contents)** 898 | 899 | 900 | ## Semicolons 901 | 902 | - **Yup.** 903 | 904 | ```javascript 905 | // bad 906 | (function() { 907 | var name = 'Skywalker' 908 | return name 909 | })() 910 | 911 | // good 912 | (function() { 913 | var name = 'Skywalker'; 914 | return name; 915 | })(); 916 | 917 | // good (guards against the function becoming an argument when two files with IIFEs are concatenated) 918 | ;(function() { 919 | var name = 'Skywalker'; 920 | return name; 921 | })(); 922 | ``` 923 | 924 | [Read more](http://stackoverflow.com/a/7365214/1712802). 925 | 926 | **[⬆ back to top](#table-of-contents)** 927 | 928 | 929 | ## Type Casting & Coercion 930 | 931 | - Perform type coercion at the beginning of the statement. 932 | - Strings: 933 | 934 | ```javascript 935 | // => this.reviewScore = 9; 936 | 937 | // bad 938 | var totalScore = this.reviewScore + ''; 939 | 940 | // good 941 | var totalScore = '' + this.reviewScore; 942 | 943 | // bad 944 | var totalScore = '' + this.reviewScore + ' total score'; 945 | 946 | // good 947 | var totalScore = this.reviewScore + ' total score'; 948 | ``` 949 | 950 | - Use `parseInt` for Numbers and always with a radix for type casting. 951 | 952 | ```javascript 953 | var inputValue = '4'; 954 | 955 | // bad 956 | var val = new Number(inputValue); 957 | 958 | // bad 959 | var val = +inputValue; 960 | 961 | // bad 962 | var val = inputValue >> 0; 963 | 964 | // bad 965 | var val = parseInt(inputValue); 966 | 967 | // good 968 | var val = Number(inputValue); 969 | 970 | // good 971 | var val = parseInt(inputValue, 10); 972 | ``` 973 | 974 | - If for whatever reason you are doing something wild and `parseInt` is your bottleneck and need to use Bitshift for [performance reasons](http://jsperf.com/coercion-vs-casting/3), leave a comment explaining why and what you're doing. 975 | 976 | ```javascript 977 | // good 978 | /** 979 | * parseInt was the reason my code was slow. 980 | * Bitshifting the String to coerce it to a 981 | * Number made it a lot faster. 982 | */ 983 | var val = inputValue >> 0; 984 | ``` 985 | 986 | - **Note:** Be careful when using bitshift operations. Numbers are represented as [64-bit values](http://es5.github.io/#x4.3.19), but Bitshift operations always return a 32-bit integer ([source](http://es5.github.io/#x11.7)). Bitshift can lead to unexpected behavior for integer values larger than 32 bits. [Discussion](https://github.com/airbnb/javascript/issues/109). Largest signed 32-bit Int is 2,147,483,647: 987 | 988 | ```javascript 989 | 2147483647 >> 0 //=> 2147483647 990 | 2147483648 >> 0 //=> -2147483648 991 | 2147483649 >> 0 //=> -2147483647 992 | ``` 993 | 994 | - Booleans: 995 | 996 | ```javascript 997 | var age = 0; 998 | 999 | // bad 1000 | var hasAge = new Boolean(age); 1001 | 1002 | // good 1003 | var hasAge = Boolean(age); 1004 | 1005 | // good 1006 | var hasAge = !!age; 1007 | ``` 1008 | 1009 | **[⬆ back to top](#table-of-contents)** 1010 | 1011 | 1012 | ## Naming Conventions 1013 | 1014 | - Avoid single letter names. Be descriptive with your naming. 1015 | 1016 | ```javascript 1017 | // bad 1018 | function q() { 1019 | // ...stuff... 1020 | } 1021 | 1022 | // good 1023 | function query() { 1024 | // ..stuff.. 1025 | } 1026 | ``` 1027 | 1028 | - Use camelCase when naming objects, functions, and instances 1029 | 1030 | ```javascript 1031 | // bad 1032 | var OBJEcttsssss = {}; 1033 | var this_is_my_object = {}; 1034 | function c() {} 1035 | var u = new user({ 1036 | name: 'Bob Parr' 1037 | }); 1038 | 1039 | // good 1040 | var thisIsMyObject = {}; 1041 | function thisIsMyFunction() {} 1042 | var user = new User({ 1043 | name: 'Bob Parr' 1044 | }); 1045 | ``` 1046 | 1047 | - Use PascalCase when naming constructors or classes 1048 | 1049 | ```javascript 1050 | // bad 1051 | function user(options) { 1052 | this.name = options.name; 1053 | } 1054 | 1055 | var bad = new user({ 1056 | name: 'nope' 1057 | }); 1058 | 1059 | // good 1060 | function User(options) { 1061 | this.name = options.name; 1062 | } 1063 | 1064 | var good = new User({ 1065 | name: 'yup' 1066 | }); 1067 | ``` 1068 | 1069 | - Use a leading underscore `_` when naming private properties 1070 | 1071 | ```javascript 1072 | // bad 1073 | this.__firstName__ = 'Panda'; 1074 | this.firstName_ = 'Panda'; 1075 | 1076 | // good 1077 | this._firstName = 'Panda'; 1078 | ``` 1079 | 1080 | - When saving a reference to `this` use `_this`. 1081 | 1082 | ```javascript 1083 | // bad 1084 | function() { 1085 | var self = this; 1086 | return function() { 1087 | console.log(self); 1088 | }; 1089 | } 1090 | 1091 | // bad 1092 | function() { 1093 | var that = this; 1094 | return function() { 1095 | console.log(that); 1096 | }; 1097 | } 1098 | 1099 | // good 1100 | function() { 1101 | var _this = this; 1102 | return function() { 1103 | console.log(_this); 1104 | }; 1105 | } 1106 | ``` 1107 | 1108 | - Name your functions. This is helpful for stack traces. 1109 | 1110 | ```javascript 1111 | // bad 1112 | var log = function(msg) { 1113 | console.log(msg); 1114 | }; 1115 | 1116 | // good 1117 | var log = function log(msg) { 1118 | console.log(msg); 1119 | }; 1120 | ``` 1121 | 1122 | - **Note:** IE8 and below exhibit some quirks with named function expressions. See [http://kangax.github.io/nfe/](http://kangax.github.io/nfe/) for more info. 1123 | 1124 | **[⬆ back to top](#table-of-contents)** 1125 | 1126 | 1127 | ## Accessors 1128 | 1129 | - Accessor functions for properties are not required 1130 | - If you do make accessor functions use getVal() and setVal('hello') 1131 | 1132 | ```javascript 1133 | // bad 1134 | dragon.age(); 1135 | 1136 | // good 1137 | dragon.getAge(); 1138 | 1139 | // bad 1140 | dragon.age(25); 1141 | 1142 | // good 1143 | dragon.setAge(25); 1144 | ``` 1145 | 1146 | - If the property is a boolean, use isVal() or hasVal() 1147 | 1148 | ```javascript 1149 | // bad 1150 | if (!dragon.age()) { 1151 | return false; 1152 | } 1153 | 1154 | // good 1155 | if (!dragon.hasAge()) { 1156 | return false; 1157 | } 1158 | ``` 1159 | 1160 | - It's okay to create get() and set() functions, but be consistent. 1161 | 1162 | ```javascript 1163 | function Jedi(options) { 1164 | options || (options = {}); 1165 | var lightsaber = options.lightsaber || 'blue'; 1166 | this.set('lightsaber', lightsaber); 1167 | } 1168 | 1169 | Jedi.prototype.set = function(key, val) { 1170 | this[key] = val; 1171 | }; 1172 | 1173 | Jedi.prototype.get = function(key) { 1174 | return this[key]; 1175 | }; 1176 | ``` 1177 | 1178 | **[⬆ back to top](#table-of-contents)** 1179 | 1180 | 1181 | ## Constructors 1182 | 1183 | - Assign methods to the prototype object, instead of overwriting the prototype with a new object. Overwriting the prototype makes inheritance impossible: by resetting the prototype you'll overwrite the base! 1184 | 1185 | ```javascript 1186 | function Jedi() { 1187 | console.log('new jedi'); 1188 | } 1189 | 1190 | // bad 1191 | Jedi.prototype = { 1192 | fight: function fight() { 1193 | console.log('fighting'); 1194 | }, 1195 | 1196 | block: function block() { 1197 | console.log('blocking'); 1198 | } 1199 | }; 1200 | 1201 | // good 1202 | Jedi.prototype.fight = function fight() { 1203 | console.log('fighting'); 1204 | }; 1205 | 1206 | Jedi.prototype.block = function block() { 1207 | console.log('blocking'); 1208 | }; 1209 | ``` 1210 | 1211 | - Methods can return `this` to help with method chaining. 1212 | 1213 | ```javascript 1214 | // bad 1215 | Jedi.prototype.jump = function() { 1216 | this.jumping = true; 1217 | return true; 1218 | }; 1219 | 1220 | Jedi.prototype.setHeight = function(height) { 1221 | this.height = height; 1222 | }; 1223 | 1224 | var luke = new Jedi(); 1225 | luke.jump(); // => true 1226 | luke.setHeight(20) // => undefined 1227 | 1228 | // good 1229 | Jedi.prototype.jump = function() { 1230 | this.jumping = true; 1231 | return this; 1232 | }; 1233 | 1234 | Jedi.prototype.setHeight = function(height) { 1235 | this.height = height; 1236 | return this; 1237 | }; 1238 | 1239 | var luke = new Jedi(); 1240 | 1241 | luke.jump() 1242 | .setHeight(20); 1243 | ``` 1244 | 1245 | 1246 | - It's okay to write a custom toString() method, just make sure it works successfully and causes no side effects. 1247 | 1248 | ```javascript 1249 | function Jedi(options) { 1250 | options || (options = {}); 1251 | this.name = options.name || 'no name'; 1252 | } 1253 | 1254 | Jedi.prototype.getName = function getName() { 1255 | return this.name; 1256 | }; 1257 | 1258 | Jedi.prototype.toString = function toString() { 1259 | return 'Jedi - ' + this.getName(); 1260 | }; 1261 | ``` 1262 | 1263 | **[⬆ back to top](#table-of-contents)** 1264 | 1265 | 1266 | ## Events 1267 | 1268 | - When attaching data payloads to events (whether DOM events or something more proprietary like Backbone events), pass a hash instead of a raw value. This allows a subsequent contributor to add more data to the event payload without finding and updating every handler for the event. For example, instead of: 1269 | 1270 | ```js 1271 | // bad 1272 | $(this).trigger('listingUpdated', listing.id); 1273 | 1274 | ... 1275 | 1276 | $(this).on('listingUpdated', function(e, listingId) { 1277 | // do something with listingId 1278 | }); 1279 | ``` 1280 | 1281 | prefer: 1282 | 1283 | ```js 1284 | // good 1285 | $(this).trigger('listingUpdated', { listingId : listing.id }); 1286 | 1287 | ... 1288 | 1289 | $(this).on('listingUpdated', function(e, data) { 1290 | // do something with data.listingId 1291 | }); 1292 | ``` 1293 | 1294 | **[⬆ back to top](#table-of-contents)** 1295 | 1296 | 1297 | ## Modules 1298 | 1299 | - The module should start with a `!`. This ensures that if a malformed module forgets to include a final semicolon there aren't errors in production when the scripts get concatenated. [Explanation](https://github.com/airbnb/javascript/issues/44#issuecomment-13063933) 1300 | - The file should be named with camelCase, live in a folder with the same name, and match the name of the single export. 1301 | - Add a method called `noConflict()` that sets the exported module to the previous version and returns this one. 1302 | - Always declare `'use strict';` at the top of the module. 1303 | 1304 | ```javascript 1305 | // fancyInput/fancyInput.js 1306 | 1307 | !function(global) { 1308 | 'use strict'; 1309 | 1310 | var previousFancyInput = global.FancyInput; 1311 | 1312 | function FancyInput(options) { 1313 | this.options = options || {}; 1314 | } 1315 | 1316 | FancyInput.noConflict = function noConflict() { 1317 | global.FancyInput = previousFancyInput; 1318 | return FancyInput; 1319 | }; 1320 | 1321 | global.FancyInput = FancyInput; 1322 | }(this); 1323 | ``` 1324 | 1325 | **[⬆ back to top](#table-of-contents)** 1326 | 1327 | 1328 | ## jQuery 1329 | 1330 | - Prefix jQuery object variables with a `$`. 1331 | 1332 | ```javascript 1333 | // bad 1334 | var sidebar = $('.sidebar'); 1335 | 1336 | // good 1337 | var $sidebar = $('.sidebar'); 1338 | ``` 1339 | 1340 | - Cache jQuery lookups. 1341 | 1342 | ```javascript 1343 | // bad 1344 | function setSidebar() { 1345 | $('.sidebar').hide(); 1346 | 1347 | // ...stuff... 1348 | 1349 | $('.sidebar').css({ 1350 | 'background-color': 'pink' 1351 | }); 1352 | } 1353 | 1354 | // good 1355 | function setSidebar() { 1356 | var $sidebar = $('.sidebar'); 1357 | $sidebar.hide(); 1358 | 1359 | // ...stuff... 1360 | 1361 | $sidebar.css({ 1362 | 'background-color': 'pink' 1363 | }); 1364 | } 1365 | ``` 1366 | 1367 | - For DOM queries use Cascading `$('.sidebar ul')` or parent > child `$('.sidebar > ul')`. [jsPerf](http://jsperf.com/jquery-find-vs-context-sel/16) 1368 | - Use `find` with scoped jQuery object queries. 1369 | 1370 | ```javascript 1371 | // bad 1372 | $('ul', '.sidebar').hide(); 1373 | 1374 | // bad 1375 | $('.sidebar').find('ul').hide(); 1376 | 1377 | // good 1378 | $('.sidebar ul').hide(); 1379 | 1380 | // good 1381 | $('.sidebar > ul').hide(); 1382 | 1383 | // good 1384 | $sidebar.find('ul').hide(); 1385 | ``` 1386 | 1387 | **[⬆ back to top](#table-of-contents)** 1388 | 1389 | 1390 | ## ECMAScript 5 Compatibility 1391 | 1392 | - Refer to [Kangax](https://twitter.com/kangax/)'s ES5 [compatibility table](http://kangax.github.com/es5-compat-table/) 1393 | 1394 | **[⬆ back to top](#table-of-contents)** 1395 | 1396 | 1397 | ## Testing 1398 | 1399 | - **Yup.** 1400 | 1401 | ```javascript 1402 | function() { 1403 | return true; 1404 | } 1405 | ``` 1406 | 1407 | **[⬆ back to top](#table-of-contents)** 1408 | 1409 | 1410 | ## Performance 1411 | 1412 | - [On Layout & Web Performance](http://kellegous.com/j/2013/01/26/layout-performance/) 1413 | - [String vs Array Concat](http://jsperf.com/string-vs-array-concat/2) 1414 | - [Try/Catch Cost In a Loop](http://jsperf.com/try-catch-in-loop-cost) 1415 | - [Bang Function](http://jsperf.com/bang-function) 1416 | - [jQuery Find vs Context, Selector](http://jsperf.com/jquery-find-vs-context-sel/13) 1417 | - [innerHTML vs textContent for script text](http://jsperf.com/innerhtml-vs-textcontent-for-script-text) 1418 | - [Long String Concatenation](http://jsperf.com/ya-string-concat) 1419 | - Loading... 1420 | 1421 | **[⬆ back to top](#table-of-contents)** 1422 | 1423 | 1424 | ## Resources 1425 | 1426 | 1427 | **Read This** 1428 | 1429 | - [Annotated ECMAScript 5.1](http://es5.github.com/) 1430 | 1431 | **Other Styleguides** 1432 | 1433 | - [Google JavaScript Style Guide](http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml) 1434 | - [jQuery Core Style Guidelines](http://docs.jquery.com/JQuery_Core_Style_Guidelines) 1435 | - [Principles of Writing Consistent, Idiomatic JavaScript](https://github.com/rwldrn/idiomatic.js/) 1436 | 1437 | **Other Styles** 1438 | 1439 | - [Naming this in nested functions](https://gist.github.com/4135065) - Christian Johansen 1440 | - [Conditional Callbacks](https://github.com/airbnb/javascript/issues/52) 1441 | - [Popular JavaScript Coding Conventions on Github](http://sideeffect.kr/popularconvention/#javascript) 1442 | 1443 | **Further Reading** 1444 | 1445 | - [Understanding JavaScript Closures](http://javascriptweblog.wordpress.com/2010/10/25/understanding-javascript-closures/) - Angus Croll 1446 | - [Basic JavaScript for the impatient programmer](http://www.2ality.com/2013/06/basic-javascript.html) - Dr. Axel Rauschmayer 1447 | - [You Might Not Need jQuery](http://youmightnotneedjquery.com/) - Zack Bloom & Adam Schwartz 1448 | - [ES6 Features](https://github.com/lukehoban/es6features) - Luke Hoban 1449 | 1450 | **Books** 1451 | 1452 | - [JavaScript: The Good Parts](http://www.amazon.com/JavaScript-Good-Parts-Douglas-Crockford/dp/0596517742) - Douglas Crockford 1453 | - [JavaScript Patterns](http://www.amazon.com/JavaScript-Patterns-Stoyan-Stefanov/dp/0596806752) - Stoyan Stefanov 1454 | - [Pro JavaScript Design Patterns](http://www.amazon.com/JavaScript-Design-Patterns-Recipes-Problem-Solution/dp/159059908X) - Ross Harmes and Dustin Diaz 1455 | - [High Performance Web Sites: Essential Knowledge for Front-End Engineers](http://www.amazon.com/High-Performance-Web-Sites-Essential/dp/0596529309) - Steve Souders 1456 | - [Maintainable JavaScript](http://www.amazon.com/Maintainable-JavaScript-Nicholas-C-Zakas/dp/1449327680) - Nicholas C. Zakas 1457 | - [JavaScript Web Applications](http://www.amazon.com/JavaScript-Web-Applications-Alex-MacCaw/dp/144930351X) - Alex MacCaw 1458 | - [Pro JavaScript Techniques](http://www.amazon.com/Pro-JavaScript-Techniques-John-Resig/dp/1590597273) - John Resig 1459 | - [Smashing Node.js: JavaScript Everywhere](http://www.amazon.com/Smashing-Node-js-JavaScript-Everywhere-Magazine/dp/1119962595) - Guillermo Rauch 1460 | - [Secrets of the JavaScript Ninja](http://www.amazon.com/Secrets-JavaScript-Ninja-John-Resig/dp/193398869X) - John Resig and Bear Bibeault 1461 | - [Human JavaScript](http://humanjavascript.com/) - Henrik Joreteg 1462 | - [Superhero.js](http://superherojs.com/) - Kim Joar Bekkelund, Mads Mobæk, & Olav Bjorkoy 1463 | - [JSBooks](http://jsbooks.revolunet.com/) 1464 | - [Third Party JavaScript](http://manning.com/vinegar/) - Ben Vinegar and Anton Kovalyov 1465 | 1466 | **Blogs** 1467 | 1468 | - [DailyJS](http://dailyjs.com/) 1469 | - [JavaScript Weekly](http://javascriptweekly.com/) 1470 | - [JavaScript, JavaScript...](http://javascriptweblog.wordpress.com/) 1471 | - [Bocoup Weblog](http://weblog.bocoup.com/) 1472 | - [Adequately Good](http://www.adequatelygood.com/) 1473 | - [NCZOnline](http://www.nczonline.net/) 1474 | - [Perfection Kills](http://perfectionkills.com/) 1475 | - [Ben Alman](http://benalman.com/) 1476 | - [Dmitry Baranovskiy](http://dmitry.baranovskiy.com/) 1477 | - [Dustin Diaz](http://dustindiaz.com/) 1478 | - [nettuts](http://net.tutsplus.com/?s=javascript) 1479 | 1480 | **[⬆ back to top](#table-of-contents)** 1481 | 1482 | ## In the Wild 1483 | 1484 | This is a list of organizations that are using this style guide. Send us a pull request or open an issue and we'll add you to the list. 1485 | 1486 | - **Aan Zee**: [AanZee/javascript](https://github.com/AanZee/javascript) 1487 | - **Airbnb**: [airbnb/javascript](https://github.com/airbnb/javascript) 1488 | - **American Insitutes for Research**: [AIRAST/javascript](https://github.com/AIRAST/javascript) 1489 | - **Compass Learning**: [compasslearning/javascript-style-guide](https://github.com/compasslearning/javascript-style-guide) 1490 | - **DailyMotion**: [dailymotion/javascript](https://github.com/dailymotion/javascript) 1491 | - **Digitpaint** [digitpaint/javascript](https://github.com/digitpaint/javascript) 1492 | - **ExactTarget**: [ExactTarget/javascript](https://github.com/ExactTarget/javascript) 1493 | - **Gawker Media**: [gawkermedia/javascript](https://github.com/gawkermedia/javascript) 1494 | - **GeneralElectric**: [GeneralElectric/javascript](https://github.com/GeneralElectric/javascript) 1495 | - **GoodData**: [gooddata/gdc-js-style](https://github.com/gooddata/gdc-js-style) 1496 | - **Grooveshark**: [grooveshark/javascript](https://github.com/grooveshark/javascript) 1497 | - **How About We**: [howaboutwe/javascript](https://github.com/howaboutwe/javascript) 1498 | - **Intent Media**: [intentmedia/javascript](https://github.com/intentmedia/javascript) 1499 | - **Mighty Spring**: [mightyspring/javascript](https://github.com/mightyspring/javascript) 1500 | - **MinnPost**: [MinnPost/javascript](https://github.com/MinnPost/javascript) 1501 | - **ModCloth**: [modcloth/javascript](https://github.com/modcloth/javascript) 1502 | - **Money Advice Service**: [moneyadviceservice/javascript](https://github.com/moneyadviceservice/javascript) 1503 | - **Muber**: [muber/javascript](https://github.com/muber/javascript) 1504 | - **National Geographic**: [natgeo/javascript](https://github.com/natgeo/javascript) 1505 | - **National Park Service**: [nationalparkservice/javascript](https://github.com/nationalparkservice/javascript) 1506 | - **Orion Health**: [orionhealth/javascript](https://github.com/orionhealth/javascript) 1507 | - **Peerby**: [Peerby/javascript](https://github.com/Peerby/javascript) 1508 | - **Razorfish**: [razorfish/javascript-style-guide](https://github.com/razorfish/javascript-style-guide) 1509 | - **reddit**: [reddit/styleguide/javascript](https://github.com/reddit/styleguide/tree/master/javascript) 1510 | - **REI**: [reidev/js-style-guide](https://github.com/reidev/js-style-guide) 1511 | - **Ripple**: [ripple/javascript-style-guide](https://github.com/ripple/javascript-style-guide) 1512 | - **SeekingAlpha**: [seekingalpha/javascript-style-guide](https://github.com/seekingalpha/javascript-style-guide) 1513 | - **Shutterfly**: [shutterfly/javascript](https://github.com/shutterfly/javascript) 1514 | - **TheLadders**: [TheLadders/javascript](https://github.com/TheLadders/javascript) 1515 | - **Userify**: [userify/javascript](https://github.com/userify/javascript) 1516 | - **Zillow**: [zillow/javascript](https://github.com/zillow/javascript) 1517 | - **ZocDoc**: [ZocDoc/javascript](https://github.com/ZocDoc/javascript) 1518 | 1519 | ## Translation 1520 | 1521 | This style guide is also available in other languages: 1522 | 1523 | - :de: **German**: [timofurrer/javascript-style-guide](https://github.com/timofurrer/javascript-style-guide) 1524 | - :jp: **Japanese**: [mitsuruog/javacript-style-guide](https://github.com/mitsuruog/javacript-style-guide) 1525 | - :br: **Portuguese**: [armoucar/javascript-style-guide](https://github.com/armoucar/javascript-style-guide) 1526 | - :cn: **Chinese**: [adamlu/javascript-style-guide](https://github.com/adamlu/javascript-style-guide) 1527 | - :es: **Spanish**: [paolocarrasco/javascript-style-guide](https://github.com/paolocarrasco/javascript-style-guide) 1528 | - :kr: **Korean**: [tipjs/javascript-style-guide](https://github.com/tipjs/javascript-style-guide) 1529 | - :fr: **French**: [nmussy/javascript-style-guide](https://github.com/nmussy/javascript-style-guide) 1530 | - :ru: **Russian**: [uprock/javascript](https://github.com/uprock/javascript) 1531 | - :bg: **Bulgarian**: [borislavvv/javascript](https://github.com/borislavvv/javascript) 1532 | 1533 | ## The JavaScript Style Guide Guide 1534 | 1535 | - [Reference](https://github.com/airbnb/javascript/wiki/The-JavaScript-Style-Guide-Guide) 1536 | 1537 | ## Contributors 1538 | 1539 | - [View Contributors](https://github.com/airbnb/javascript/graphs/contributors) 1540 | 1541 | 1542 | ## License 1543 | 1544 | (The MIT License) 1545 | 1546 | Copyright (c) 2014 Airbnb 1547 | 1548 | Permission is hereby granted, free of charge, to any person obtaining 1549 | a copy of this software and associated documentation files (the 1550 | 'Software'), to deal in the Software without restriction, including 1551 | without limitation the rights to use, copy, modify, merge, publish, 1552 | distribute, sublicense, and/or sell copies of the Software, and to 1553 | permit persons to whom the Software is furnished to do so, subject to 1554 | the following conditions: 1555 | 1556 | The above copyright notice and this permission notice shall be 1557 | included in all copies or substantial portions of the Software. 1558 | 1559 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 1560 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1561 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 1562 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 1563 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 1564 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 1565 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 1566 | 1567 | **[⬆ back to top](#table-of-contents)** 1568 | 1569 | # }; 1570 | -------------------------------------------------------------------------------- /linters/SublimeLinter/SublimeLinter.sublime-settings: -------------------------------------------------------------------------------- 1 | /** 2 | * Airbnb JSHint settings for use with SublimeLinter and Sublime Text 2. 3 | * 4 | * 1. Install SublimeLinter at https://github.com/SublimeLinter/SublimeLinter 5 | * 2. Open user preferences for the SublimeLinter package in Sublime Text 2 6 | * * For Mac OS X go to _Sublime Text 2_ > _Preferences_ > _Package Settings_ > _SublimeLinter_ > _Settings - User_ 7 | * 3. Paste the contents of this file into your settings file 8 | * 4. Save the settings file 9 | * 10 | * @version 0.3.0 11 | * @see https://github.com/SublimeLinter/SublimeLinter 12 | * @see http://www.jshint.com/docs/ 13 | */ 14 | { 15 | "jshint_options": 16 | { 17 | /* 18 | * ENVIRONMENTS 19 | * ================= 20 | */ 21 | 22 | // Define globals exposed by modern browsers. 23 | "browser": true, 24 | 25 | // Define globals exposed by jQuery. 26 | "jquery": true, 27 | 28 | // Define globals exposed by Node.js. 29 | "node": true, 30 | 31 | /* 32 | * ENFORCING OPTIONS 33 | * ================= 34 | */ 35 | 36 | // Force all variable names to use either camelCase style or UPPER_CASE 37 | // with underscores. 38 | "camelcase": true, 39 | 40 | // Prohibit use of == and != in favor of === and !==. 41 | "eqeqeq": true, 42 | 43 | // Suppress warnings about == null comparisons. 44 | "eqnull": true, 45 | 46 | // Enforce tab width of 2 spaces. 47 | "indent": 2, 48 | 49 | // Prohibit use of a variable before it is defined. 50 | "latedef": true, 51 | 52 | // Require capitalized names for constructor functions. 53 | "newcap": true, 54 | 55 | // Enforce use of single quotation marks for strings. 56 | "quotmark": "single", 57 | 58 | // Prohibit trailing whitespace. 59 | "trailing": true, 60 | 61 | // Prohibit use of explicitly undeclared variables. 62 | "undef": true, 63 | 64 | // Warn when variables are defined but never used. 65 | "unused": true, 66 | 67 | // Enforce line length to 80 characters 68 | "maxlen": 80, 69 | 70 | // Enforce placing 'use strict' at the top function scope 71 | "strict": true 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /linters/jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | /* 3 | * ENVIRONMENTS 4 | * ================= 5 | */ 6 | 7 | // Define globals exposed by modern browsers. 8 | "browser": true, 9 | 10 | // Define globals exposed by jQuery. 11 | "jquery": true, 12 | 13 | // Define globals exposed by Node.js. 14 | "node": true, 15 | 16 | /* 17 | * ENFORCING OPTIONS 18 | * ================= 19 | */ 20 | 21 | // Force all variable names to use either camelCase style or UPPER_CASE 22 | // with underscores. 23 | "camelcase": true, 24 | 25 | // Prohibit use of == and != in favor of === and !==. 26 | "eqeqeq": true, 27 | 28 | // Enforce tab width of 2 spaces. 29 | "indent": 2, 30 | 31 | // Prohibit use of a variable before it is defined. 32 | "latedef": true, 33 | 34 | // Enforce line length to 80 characters 35 | "maxlen": 80, 36 | 37 | // Require capitalized names for constructor functions. 38 | "newcap": true, 39 | 40 | // Enforce use of single quotation marks for strings. 41 | "quotmark": "single", 42 | 43 | // Enforce placing 'use strict' at the top function scope 44 | "strict": true, 45 | 46 | // Prohibit use of explicitly undeclared variables. 47 | "undef": true, 48 | 49 | // Warn when variables are defined but never used. 50 | "unused": true, 51 | 52 | /* 53 | * RELAXING OPTIONS 54 | * ================= 55 | */ 56 | 57 | // Suppress warnings about == null comparisons. 58 | "eqnull": true 59 | } 60 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "airbnb-style", 3 | "version": "1.0.0", 4 | "description": "A mostly reasonable approach to JavaScript.", 5 | "scripts": { 6 | "test": "echo \"Error: no test specified\" && exit 1" 7 | }, 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/airbnb/javascript.git" 11 | }, 12 | "keywords": [ 13 | "style guide", 14 | "lint", 15 | "airbnb" 16 | ], 17 | "author": "Harrison Shoff (https://twitter.com/hshoff)", 18 | "license": "MIT", 19 | "bugs": { 20 | "url": "https://github.com/airbnb/javascript/issues" 21 | }, 22 | "homepage": "https://github.com/airbnb/javascript" 23 | } 24 | --------------------------------------------------------------------------------