From 16a4ff818a791d715ab4fa1f52df5203d4f95310 Mon Sep 17 00:00:00 2001 From: Thanasis Polychronakis Date: Fri, 7 Feb 2014 19:45:36 +0200 Subject: [PATCH 01/20] update jshint file --- linters/jshintrc | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/linters/jshintrc b/linters/jshintrc index d3b47148a8..657882a0e8 100644 --- a/linters/jshintrc +++ b/linters/jshintrc @@ -1,3 +1,11 @@ +/** + * Project specific jshint linting options. + * + * Forked of Airbnb JSHint settings. + * + * @version 0.3.1 + * @see http://www.jshint.com/docs/ + */ { /* * ENVIRONMENTS @@ -5,10 +13,10 @@ */ // Define globals exposed by modern browsers. - "browser": true, + "browser": false, // Define globals exposed by jQuery. - "jquery": true, + "jquery": false, // Define globals exposed by Node.js. "node": true, @@ -49,9 +57,24 @@ // Warn when variables are defined but never used. "unused": true, - // Enforce line length to 80 characters - "maxlen": 80, + // do not complain for lack of 'use strict'; + "globalstrict": false, + "strict": false, - // Enforce placing 'use strict' at the top function scope - "strict": true + // suppress object dot notation warnings, we know what we're doing + "sub": true, + + + /** + * PROJECT GLOBALS + * ================ + * + */ + "predef": [ + "setup", + "teardown", + "test", + "suite", + "assert" + ] } From 65fdbb4687729ec7e1d9801682eb9c5991cd1a6e Mon Sep 17 00:00:00 2001 From: Thanasis Polychronakis Date: Fri, 7 Feb 2014 19:46:39 +0200 Subject: [PATCH 02/20] update jshint file to 0.4.0 --- linters/jshintrc | 50 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/linters/jshintrc b/linters/jshintrc index 657882a0e8..9d1bd8fedb 100644 --- a/linters/jshintrc +++ b/linters/jshintrc @@ -3,7 +3,7 @@ * * Forked of Airbnb JSHint settings. * - * @version 0.3.1 + * @version 0.4.0 * @see http://www.jshint.com/docs/ */ { @@ -21,13 +21,41 @@ // Define globals exposed by Node.js. "node": true, + /* + * TABS AND QUOTES + * ================== + */ + // Enforce tab width of 2 spaces. + "indent": 2, + + // Enforce use of single quotation marks for strings. + "quotmark": "single", + /* * ENFORCING OPTIONS * ================= */ - // Force all variable names to use either camelCase style or UPPER_CASE - // with underscores. + // This option requires you to always put curly braces + // around blocks in loops and conditionals. + "curly": true, + + // This option prohibits the use of immediate function + // invocations without wrapping them in parentheses. + "immed": true, + + // This option prohibits the use of arguments.caller + // and arguments.callee. Both .caller and .callee make + // quite a few optimizations impossible so they were + // deprecated in future versions of JavaScript. + "noarg": true, + + // This option suppresses warnings about the use of + // assignments in cases where comparisons are expected + "boss": true, + + // Force all variable names to use either camelCase style + // or UPPER_CASE with underscores. "camelcase": true, // Prohibit use of == and != in favor of === and !==. @@ -36,18 +64,12 @@ // Suppress warnings about == null comparisons. "eqnull": true, - // Enforce tab width of 2 spaces. - "indent": 2, - // Prohibit use of a variable before it is defined. "latedef": true, // Require capitalized names for constructor functions. "newcap": true, - // Enforce use of single quotation marks for strings. - "quotmark": "single", - // Prohibit trailing whitespace. "trailing": true, @@ -64,17 +86,21 @@ // suppress object dot notation warnings, we know what we're doing "sub": true, - /** * PROJECT GLOBALS * ================ * */ "predef": [ + /* MOCHA */ + "suite": false, + "test": false, + "before": false, + "beforeEach": false, + "after": false, + "afterEach": false "setup", "teardown", - "test", - "suite", "assert" ] } From 1f1b3de9bd40d52ec742135afdb5966131108be6 Mon Sep 17 00:00:00 2001 From: Thanasis Polychronakis Date: Fri, 7 Feb 2014 19:50:21 +0200 Subject: [PATCH 03/20] add url to jshint fork --- linters/jshintrc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/linters/jshintrc b/linters/jshintrc index 9d1bd8fedb..34b4b792f2 100644 --- a/linters/jshintrc +++ b/linters/jshintrc @@ -1,10 +1,11 @@ /** * Project specific jshint linting options. * - * Forked of Airbnb JSHint settings. + * Forked from Airbnb JSHint settings. * * @version 0.4.0 - * @see http://www.jshint.com/docs/ + * @see http://www.jshint.com/docs/ + * @see https://github.com/airbnb/javascript */ { /* From aced9f2940ceab8b6cf833a95632396c993225b7 Mon Sep 17 00:00:00 2001 From: Thanasis Polychronakis Date: Sun, 16 Feb 2014 00:35:25 +0200 Subject: [PATCH 04/20] fix globals for mocha --- linters/jshintrc | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/linters/jshintrc b/linters/jshintrc index 34b4b792f2..8160440190 100644 --- a/linters/jshintrc +++ b/linters/jshintrc @@ -3,7 +3,7 @@ * * Forked from Airbnb JSHint settings. * - * @version 0.4.0 + * @version 0.4.1 * @see http://www.jshint.com/docs/ * @see https://github.com/airbnb/javascript */ @@ -92,16 +92,16 @@ * ================ * */ - "predef": [ + "globals": { /* MOCHA */ "suite": false, "test": false, + "setup": false, "before": false, "beforeEach": false, "after": false, - "afterEach": false - "setup", - "teardown", - "assert" - ] + "afterEach": false, + "teardown": false, + "assert": false + } } From 314e32373038b0fbb2e11bf35478b8ea4dfb4667 Mon Sep 17 00:00:00 2001 From: Thanasis Polychronakis Date: Sun, 16 Feb 2014 00:58:12 +0200 Subject: [PATCH 05/20] add 'describe' mocha global --- linters/jshintrc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/linters/jshintrc b/linters/jshintrc index 8160440190..d6e6d981f0 100644 --- a/linters/jshintrc +++ b/linters/jshintrc @@ -3,7 +3,7 @@ * * Forked from Airbnb JSHint settings. * - * @version 0.4.1 + * @version 0.4.2 * @see http://www.jshint.com/docs/ * @see https://github.com/airbnb/javascript */ @@ -95,6 +95,7 @@ "globals": { /* MOCHA */ "suite": false, + "describe": false, "test": false, "setup": false, "before": false, From 2a2ef11eef3a9cb219697a039af4665fe73a5f18 Mon Sep 17 00:00:00 2001 From: Thanasis Polychronakis Date: Sun, 16 Feb 2014 01:09:26 +0200 Subject: [PATCH 06/20] add it bdd jshint --- linters/jshintrc | 1 + 1 file changed, 1 insertion(+) diff --git a/linters/jshintrc b/linters/jshintrc index d6e6d981f0..e96a7a2156 100644 --- a/linters/jshintrc +++ b/linters/jshintrc @@ -97,6 +97,7 @@ "suite": false, "describe": false, "test": false, + "it": false, "setup": false, "before": false, "beforeEach": false, From 7b686bb823c7fe48a5aab1776dfa085ce2079072 Mon Sep 17 00:00:00 2001 From: Thanasis Polychronakis Date: Sun, 16 Feb 2014 19:10:18 +0200 Subject: [PATCH 07/20] update jshint --- linters/jshintrc | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/linters/jshintrc b/linters/jshintrc index e96a7a2156..8c476c2290 100644 --- a/linters/jshintrc +++ b/linters/jshintrc @@ -3,9 +3,10 @@ * * Forked from Airbnb JSHint settings. * - * @version 0.4.2 + * @version 0.4.3 + * @source * @see http://www.jshint.com/docs/ - * @see https://github.com/airbnb/javascript + * @see https://github.com/airbnb/javascript * Forked of Airbnb JSHint settings. */ { /* @@ -65,12 +66,18 @@ // Suppress warnings about == null comparisons. "eqnull": true, + // Enforce tab width of 2 spaces. + "indent": 2, + // Prohibit use of a variable before it is defined. "latedef": true, // Require capitalized names for constructor functions. "newcap": true, + // Enforce use of single quotation marks for strings. + "quotmark": "single", + // Prohibit trailing whitespace. "trailing": true, @@ -87,6 +94,14 @@ // suppress object dot notation warnings, we know what we're doing "sub": true, + /** + * TEMPORARY OPTIONS + * ================= + * + * These are provisional options for legacy code. + * + */ + /** * PROJECT GLOBALS * ================ @@ -95,8 +110,8 @@ "globals": { /* MOCHA */ "suite": false, - "describe": false, "test": false, + "describe": false, "it": false, "setup": false, "before": false, From a7286c32040b3e260ec6a19120cf857454e84b0b Mon Sep 17 00:00:00 2001 From: Thanasis Polychronakis Date: Sun, 16 Feb 2014 19:10:40 +0200 Subject: [PATCH 08/20] move jshintrc to root --- linters/jshintrc => .jshintrc | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename linters/jshintrc => .jshintrc (100%) diff --git a/linters/jshintrc b/.jshintrc similarity index 100% rename from linters/jshintrc rename to .jshintrc From 02d75a9b4834358306d081d2b41a391d0ee98b92 Mon Sep 17 00:00:00 2001 From: Thanasis Polychronakis Date: Sun, 16 Feb 2014 19:11:08 +0200 Subject: [PATCH 09/20] rename linters folder --- .../SublimeLinter/SublimeLinter.sublime-settings | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {linters => editor-linters}/SublimeLinter/SublimeLinter.sublime-settings (100%) diff --git a/linters/SublimeLinter/SublimeLinter.sublime-settings b/editor-linters/SublimeLinter/SublimeLinter.sublime-settings similarity index 100% rename from linters/SublimeLinter/SublimeLinter.sublime-settings rename to editor-linters/SublimeLinter/SublimeLinter.sublime-settings From 5e491d86d31ea412b79f4a03c89bded9b32408d4 Mon Sep 17 00:00:00 2001 From: Thanasis Polychronakis Date: Sun, 16 Feb 2014 19:12:00 +0200 Subject: [PATCH 10/20] add source url and bump ver --- .jshintrc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.jshintrc b/.jshintrc index 8c476c2290..6dcc998a25 100644 --- a/.jshintrc +++ b/.jshintrc @@ -3,8 +3,8 @@ * * Forked from Airbnb JSHint settings. * - * @version 0.4.3 - * @source + * @version 0.4.4 + * @source https://github.com/thanpolas/javascript/blob/master/.jshintrc * @see http://www.jshint.com/docs/ * @see https://github.com/airbnb/javascript * Forked of Airbnb JSHint settings. */ From 6effa2bcec0061b655d9654197e6bf9c3843d548 Mon Sep 17 00:00:00 2001 From: Thanasis Polychronakis Date: Mon, 3 Mar 2014 23:30:14 +0200 Subject: [PATCH 11/20] personal flavor --- README.md | 58 +++++++++++++++++-------------------------------------- 1 file changed, 18 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index 3a477b6c50..b69264c5d4 100644 --- a/README.md +++ b/README.md @@ -47,8 +47,8 @@ + `undefined` ```javascript - var foo = 1, - bar = foo; + var foo = 1; + var bar = foo; bar = 9; @@ -61,8 +61,8 @@ + `function` ```javascript - var foo = [1, 2], - bar = foo; + var foo = [1, 2]; + var bar = foo; bar[0] = 9; @@ -147,9 +147,9 @@ - When you need to copy an array use Array#slice. [jsPerf](http://jsperf.com/converting-arguments-to-an-array/7) ```javascript - var len = items.length, - itemsCopy = [], - i; + var len = items.length; + var itemsCopy = []; + var i; // bad for (i = 0; i < len; i++) { @@ -218,10 +218,10 @@ - When programatically building up a string, use Array#join instead of string concatenation. Mostly for IE: [jsPerf](http://jsperf.com/string-vs-array-concat/2). ```javascript - var items, - messages, - length, - i; + var items; + var messages; + var length; + var i; messages = [{ state: 'success', @@ -368,40 +368,19 @@ var superPower = new SuperPower(); ``` - - Use one `var` declaration for multiple variables and declare each variable on a newline. + - Use multiple `var` declarations for multiple variables and declare each variable on a newline. ```javascript // bad - var items = getItems(); - var goSportsTeam = true; - var dragonball = 'z'; - - // good var items = getItems(), goSportsTeam = true, dragonball = 'z'; - ``` - - - 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. - - ```javascript - // bad - var i, len, dragonball, - items = getItems(), - goSportsTeam = true; - - // bad - var i, items = getItems(), - dragonball, - goSportsTeam = true, - len; // good - var items = getItems(), - goSportsTeam = true, - dragonball, - length, - i; + var items = getItems(); + var goSportsTeam = true; + var dragonball = 'z'; + ``` - Assign variables at the top of their scope. This helps avoid issues with variable declaration and assignment hoisting related issues. @@ -864,7 +843,7 @@ }; ``` - - 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)): + - Additional trailing comma: **Yeap** for Node.js **Nope** for Browsers, 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)): > 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. @@ -1286,13 +1265,12 @@ - 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) - The file should be named with camelCase, live in a folder with the same name, and match the name of the single export. - Add a method called noConflict() that sets the exported module to the previous version and returns this one. - - Always declare `'use strict';` at the top of the module. + - Do not use `'use strict';` at the top of the module! ```javascript // fancyInput/fancyInput.js !function(global) { - 'use strict'; var previousFancyInput = global.FancyInput; From 7d3a0c2dfc64364045a4c00f33c4b69edad83ac9 Mon Sep 17 00:00:00 2001 From: Thanasis Polychronakis Date: Mon, 3 Mar 2014 23:56:07 +0200 Subject: [PATCH 12/20] specify conditional testing/expected position --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index b69264c5d4..7b1012bdca 100644 --- a/README.md +++ b/README.md @@ -537,6 +537,16 @@ ## Conditional Expressions & Equality - Use `===` and `!==` over `==` and `!=`. + - Always use the testing part first and the expected value second: + + '''javascript + // bad + if (2 === values.length) {} + + // good + if (values.length === 2) {} + ``` + - Conditional expressions are evaluated using coercion with the `ToBoolean` method and always follow these simple rules: + **Objects** evaluate to **true** From 710c4691c3fceabc6739b47f944b6ab2cfe47356 Mon Sep 17 00:00:00 2001 From: Thanasis Polychronakis Date: Mon, 3 Mar 2014 23:57:33 +0200 Subject: [PATCH 13/20] sign file --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7b1012bdca..a3b4b0f1c9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,8 @@ -# Airbnb JavaScript Style Guide() { +# JavaScript Style Guide() { *A mostly reasonable approach to JavaScript* +Forked from [AirBnB's Javascript repo](https://github.com/airbnb/javascript). ## Table of Contents From b00352cb74d7d1288c6d622a86d4d2025df240cc Mon Sep 17 00:00:00 2001 From: Thanasis Polychronakis Date: Tue, 4 Mar 2014 00:32:42 +0200 Subject: [PATCH 14/20] create maintainability article --- maintainability.md | 136 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 maintainability.md diff --git a/maintainability.md b/maintainability.md new file mode 100644 index 0000000000..12376942a2 --- /dev/null +++ b/maintainability.md @@ -0,0 +1,136 @@ +# Maintainability + +Maintainability comes out of a uniform and homogeneous codebase. The fact that multiple developers are expected to read and understand existing code must always be the top and foremost priority when authoring code. After all, we write code for the purpose of reading it. + +To achieve codebase uniformity and homogeneity a certain set of rules must be agreed upon and honored by all authors. This document is about these rules. When applied properly, the whole codebase should look like it was authored by a single person. + +## Table of Contents + + 1. [Document Blocks](#docblocks) + 1. [Module Dependencies](#modules) + 1. [Module Format](#format) + +## Document Blocks + +Every method, function, property should be documented with JSDoc Tags. The [Google's Closure Compiler Annotation][gdocs] is used. The main reason being the richness of expression for describing complex data structures and creating primitives. + +```js +/** + * Helper for default value of date types. + * + * @param {number} plusTime + * @return {number} The JS timestamp the future. + */ +orm.defaultDate = function(plusTime) { + return Date.now() + plusTime; +}; +``` + +**[[⬆]](#TOC)** + +## Module Dependencies + +For the Node environment the following format of requiring modules is advised: + + 1. Require all core modules + 1. Require all packages + 1. Require all local modules + +Each devised by a new line and if possible order by lower to higher level in the stack. + +```js +// core modules +var util = require('util'); + +// packages +var __ = require('lodash'); // use double underscore for lodash +var Promise = require('bluebird'); // lodash is lower in the stack than promises +var express = require('express'); + +// local modules +var userCtrl = require('./controllers/user.ctrl'); +``` + +> **Important**: All module dependencies must be declared on the top of the file, no exceptions. + +**[[⬆]](#TOC)** + + +## Module Format + +### General Layout + +These rules only apply to Node modules. Each module should have the following structure: + +Lines must not exceed 80 columns in any file. Exceptions are markdown and markup files. + +1. The `@fileOverview` tag with a general description about what this module is about. +1. The module dependencies as described in [Module Dependencies][#modules]. +1. Declare anything that is local to the module. +1. Use only `module.exports` as a way of exporting, before any code. Beyond this point everything is attached to the exported object. +1. Declare all static properties, functions, constants or enums right after the export statement. +1. Declare all public / exported methods +1. Declare all private methods + +Even *private* methods are defined on the exported object. + +```js +/** + * @fileOverview The user Model. + */ +var util = require('util'); + +var __ = require('lodash'); +var config = require('config'); +var log = require('logg').getLogger('app.model.User'); + +var ModelMongo = require('./model-mongo'); +var helpers = require('../util/helpers'); + +/** + * The base user model. + * + * @constructor + * @extends {app.ModelMongo} + */ +var User = module.exports = function(){ + ModelMongo.apply(this, arguments); +}; +util.inherits(User, ModelMongo); +helpers.addSingletonGetter(User); + +/** + * The supported user roles. + * + * @enum {number} + */ +User.Role = { + API: 1, + ADMIN: 2, +}; + +/** + * Pre-validation middleware. Set any default values. + * + * @param {Function(Error)} next callback + * @private + * @this {mongoose.Schema} Mongoose context. + */ +User.prototype._setDefaultValues = function(next){ + next(); +}; + +/** + * Pre-Save password filter, will one-way encrypt the value. + * + * @param {Function(Error=)} next Callback. + * @this {mongoose.Schema} Mongoose context. + * @private + */ +User.prototype._hashPassword = function(next) { + next(); +}; +``` + +[gdocs]: https://developers.google.com/closure/compiler/docs/js-for-compiler?hl=en#tags + From 83495206871f8dfda32857206b2cb27cc64a5332 Mon Sep 17 00:00:00 2001 From: Thanasis Polychronakis Date: Tue, 4 Mar 2014 00:35:01 +0200 Subject: [PATCH 15/20] fixes on maintainability doc --- maintainability.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/maintainability.md b/maintainability.md index 12376942a2..c268337ec0 100644 --- a/maintainability.md +++ b/maintainability.md @@ -36,7 +36,7 @@ For the Node environment the following format of requiring modules is advised: 1. Require all packages 1. Require all local modules -Each devised by a new line and if possible order by lower to higher level in the stack. +Each separated by a new line and if possible order by lower to higher level in the stack. ```js // core modules @@ -65,7 +65,7 @@ These rules only apply to Node modules. Each module should have the following st Lines must not exceed 80 columns in any file. Exceptions are markdown and markup files. 1. The `@fileOverview` tag with a general description about what this module is about. -1. The module dependencies as described in [Module Dependencies][#modules]. +1. The module dependencies as described in [Module Dependencies](#modules). 1. Declare anything that is local to the module. 1. Use only `module.exports` as a way of exporting, before any code. Beyond this point everything is attached to the exported object. 1. Declare all static properties, functions, constants or enums right after the export statement. From f0d4bedc2539d21abd193ebde6ff43b1e1f34517 Mon Sep 17 00:00:00 2001 From: Thanasis Polychronakis Date: Tue, 4 Mar 2014 00:36:18 +0200 Subject: [PATCH 16/20] remove editor linters folder --- .../SublimeLinter.sublime-settings | 73 ------------------- 1 file changed, 73 deletions(-) delete mode 100644 editor-linters/SublimeLinter/SublimeLinter.sublime-settings diff --git a/editor-linters/SublimeLinter/SublimeLinter.sublime-settings b/editor-linters/SublimeLinter/SublimeLinter.sublime-settings deleted file mode 100644 index 12360f3f1c..0000000000 --- a/editor-linters/SublimeLinter/SublimeLinter.sublime-settings +++ /dev/null @@ -1,73 +0,0 @@ -/** - * Airbnb JSHint settings for use with SublimeLinter and Sublime Text 2. - * - * 1. Install SublimeLinter at https://github.com/SublimeLinter/SublimeLinter - * 2. Open user preferences for the SublimeLinter package in Sublime Text 2 - * * For Mac OS X go to _Sublime Text 2_ > _Preferences_ > _Package Settings_ > _SublimeLinter_ > _Settings - User_ - * 3. Paste the contents of this file into your settings file - * 4. Save the settings file - * - * @version 0.3.0 - * @see https://github.com/SublimeLinter/SublimeLinter - * @see http://www.jshint.com/docs/ - */ -{ - "jshint_options": - { - /* - * ENVIRONMENTS - * ================= - */ - - // Define globals exposed by modern browsers. - "browser": true, - - // Define globals exposed by jQuery. - "jquery": true, - - // Define globals exposed by Node.js. - "node": true, - - /* - * ENFORCING OPTIONS - * ================= - */ - - // Force all variable names to use either camelCase style or UPPER_CASE - // with underscores. - "camelcase": true, - - // Prohibit use of == and != in favor of === and !==. - "eqeqeq": true, - - // Suppress warnings about == null comparisons. - "eqnull": true, - - // Enforce tab width of 2 spaces. - "indent": 2, - - // Prohibit use of a variable before it is defined. - "latedef": true, - - // Require capitalized names for constructor functions. - "newcap": true, - - // Enforce use of single quotation marks for strings. - "quotmark": "single", - - // Prohibit trailing whitespace. - "trailing": true, - - // Prohibit use of explicitly undeclared variables. - "undef": true, - - // Warn when variables are defined but never used. - "unused": true, - - // Enforce line length to 80 characters - "maxlen": 80, - - // Enforce placing 'use strict' at the top function scope - "strict": true - } -} From f80fd31018423ca1f7fa56ea54a3f0add14f92d6 Mon Sep 17 00:00:00 2001 From: Thanasis Polychronakis Date: Sat, 8 Mar 2014 19:08:33 +0200 Subject: [PATCH 17/20] add more keywords, remove duplicate declarations --- .jshintrc | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/.jshintrc b/.jshintrc index 6dcc998a25..a0a9c0ef09 100644 --- a/.jshintrc +++ b/.jshintrc @@ -3,7 +3,7 @@ * * Forked from Airbnb JSHint settings. * - * @version 0.4.4 + * @version 0.4.5 * @source https://github.com/thanpolas/javascript/blob/master/.jshintrc * @see http://www.jshint.com/docs/ * @see https://github.com/airbnb/javascript * Forked of Airbnb JSHint settings. @@ -66,18 +66,12 @@ // Suppress warnings about == null comparisons. "eqnull": true, - // Enforce tab width of 2 spaces. - "indent": 2, - // Prohibit use of a variable before it is defined. "latedef": true, // Require capitalized names for constructor functions. "newcap": true, - // Enforce use of single quotation marks for strings. - "quotmark": "single", - // Prohibit trailing whitespace. "trailing": true, @@ -91,9 +85,34 @@ "globalstrict": false, "strict": false, + // This option suppresses warnings about the use of expressions where + // normally you would expect to see assignments or function calls. + // Most of the time, such code is a typo. However, it is not forbidden + // by the spec and that's why this warning is optional. + "expr": false, + + // This option suppresses warnings about the use of eval. + // The use of eval is discouraged because it can make your code + // vulnerable to various injection attacks and it makes it hard for + // JavaScript interpreter to do certain optimizations. + "evil": false, + + // This option suppresses warnings about comma-first coding style. + "laxcomma": false, + // suppress object dot notation warnings, we know what we're doing "sub": true, + // This option defines globals that are usually used for logging poor-man's + // debugging: console, alert, etc. It is usually a good idea to not ship + // them in production because, for example, console.log breaks in legacy + // versions of Internet Explorer. + "devel": false, + + // This option suppresses warnings about mixed tabs and spaces when the + // latter are used for alignmnent only. The technique is called SmartTabs. + "smarttabs": false, + /** * TEMPORARY OPTIONS * ================= From 2ad924b72ef5529db2ad1af1c96c59893d43440e Mon Sep 17 00:00:00 2001 From: Thanasis Polychronakis Date: Tue, 11 Mar 2014 17:24:50 +0200 Subject: [PATCH 18/20] add .bind() link & blurp --- maintainability.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/maintainability.md b/maintainability.md index c268337ec0..433632c450 100644 --- a/maintainability.md +++ b/maintainability.md @@ -132,5 +132,36 @@ User.prototype._hashPassword = function(next) { }; ``` +## Optimizations + +Random snippets of best practices and performance gains. + +#### Do not use .bind() + +[Bind's implementation is slow][bind slow], until V8 gets passed that issue use closures: + +```js + +app.add = function(a, b) { + + // bad + asyncFn(function() { + this.a = a; + }.bind(this)); + + // good + var self = this; + asyncFn(function() { + self.a = a; + }); + +}; +``` + +#### Use .bind() + +You can use `.bind()` during application boot-time for binding methods. Boot-time occurs only once so the performance hit by de-optimized methods and practices is non consequential. + [gdocs]: https://developers.google.com/closure/compiler/docs/js-for-compiler?hl=en#tags +[bind slow]: http://stackoverflow.com/questions/17638305/why-is-bind-slower-than-a-closure/17638540#17638540 From 45cfa03b1a45a87b0bdc13432a1e21a9e5c919a4 Mon Sep 17 00:00:00 2001 From: Thanasis Polychronakis Date: Fri, 27 Jun 2014 17:18:29 +0300 Subject: [PATCH 19/20] add move notice --- maintainability.md | 168 +-------------------------------------------- 1 file changed, 2 insertions(+), 166 deletions(-) diff --git a/maintainability.md b/maintainability.md index 433632c450..6652b8ce19 100644 --- a/maintainability.md +++ b/maintainability.md @@ -1,167 +1,3 @@ -# Maintainability - -Maintainability comes out of a uniform and homogeneous codebase. The fact that multiple developers are expected to read and understand existing code must always be the top and foremost priority when authoring code. After all, we write code for the purpose of reading it. - -To achieve codebase uniformity and homogeneity a certain set of rules must be agreed upon and honored by all authors. This document is about these rules. When applied properly, the whole codebase should look like it was authored by a single person. - -## Table of Contents - - 1. [Document Blocks](#docblocks) - 1. [Module Dependencies](#modules) - 1. [Module Format](#format) - -## Document Blocks - -Every method, function, property should be documented with JSDoc Tags. The [Google's Closure Compiler Annotation][gdocs] is used. The main reason being the richness of expression for describing complex data structures and creating primitives. - -```js -/** - * Helper for default value of date types. - * - * @param {number} plusTime - * @return {number} The JS timestamp the future. - */ -orm.defaultDate = function(plusTime) { - return Date.now() + plusTime; -}; -``` - -**[[⬆]](#TOC)** - -## Module Dependencies - -For the Node environment the following format of requiring modules is advised: - - 1. Require all core modules - 1. Require all packages - 1. Require all local modules - -Each separated by a new line and if possible order by lower to higher level in the stack. - -```js -// core modules -var util = require('util'); - -// packages -var __ = require('lodash'); // use double underscore for lodash -var Promise = require('bluebird'); // lodash is lower in the stack than promises -var express = require('express'); - -// local modules -var userCtrl = require('./controllers/user.ctrl'); -``` - -> **Important**: All module dependencies must be declared on the top of the file, no exceptions. - -**[[⬆]](#TOC)** - - -## Module Format - -### General Layout - -These rules only apply to Node modules. Each module should have the following structure: - -Lines must not exceed 80 columns in any file. Exceptions are markdown and markup files. - -1. The `@fileOverview` tag with a general description about what this module is about. -1. The module dependencies as described in [Module Dependencies](#modules). -1. Declare anything that is local to the module. -1. Use only `module.exports` as a way of exporting, before any code. Beyond this point everything is attached to the exported object. -1. Declare all static properties, functions, constants or enums right after the export statement. -1. Declare all public / exported methods -1. Declare all private methods - -Even *private* methods are defined on the exported object. - -```js -/** - * @fileOverview The user Model. - */ -var util = require('util'); - -var __ = require('lodash'); -var config = require('config'); -var log = require('logg').getLogger('app.model.User'); - -var ModelMongo = require('./model-mongo'); -var helpers = require('../util/helpers'); - -/** - * The base user model. - * - * @constructor - * @extends {app.ModelMongo} - */ -var User = module.exports = function(){ - ModelMongo.apply(this, arguments); -}; -util.inherits(User, ModelMongo); -helpers.addSingletonGetter(User); - -/** - * The supported user roles. - * - * @enum {number} - */ -User.Role = { - API: 1, - ADMIN: 2, -}; - -/** - * Pre-validation middleware. Set any default values. - * - * @param {Function(Error)} next callback - * @private - * @this {mongoose.Schema} Mongoose context. - */ -User.prototype._setDefaultValues = function(next){ - next(); -}; - -/** - * Pre-Save password filter, will one-way encrypt the value. - * - * @param {Function(Error=)} next Callback. - * @this {mongoose.Schema} Mongoose context. - * @private - */ -User.prototype._hashPassword = function(next) { - next(); -}; -``` - -## Optimizations - -Random snippets of best practices and performance gains. - -#### Do not use .bind() - -[Bind's implementation is slow][bind slow], until V8 gets passed that issue use closures: - -```js - -app.add = function(a, b) { - - // bad - asyncFn(function() { - this.a = a; - }.bind(this)); - - // good - var self = this; - asyncFn(function() { - self.a = a; - }); - -}; -``` - -#### Use .bind() - -You can use `.bind()` during application boot-time for binding methods. Boot-time occurs only once so the performance hit by de-optimized methods and practices is non consequential. - -[gdocs]: https://developers.google.com/closure/compiler/docs/js-for-compiler?hl=en#tags -[bind slow]: http://stackoverflow.com/questions/17638305/why-is-bind-slower-than-a-closure/17638540#17638540 +# Moved +Moved to [thanpolas/practice](https://github.com/thanpolas/Practice/blob/master/Node.js.md) repository. From 4145b949fa9e3e7226416c8b44203bab4b6030d4 Mon Sep 17 00:00:00 2001 From: Thanasis Polychronakis Date: Thu, 7 Aug 2014 12:19:36 +0300 Subject: [PATCH 20/20] move to practice repo --- .jshintrc | 147 +---- README.md | 1535 +---------------------------------------------------- 2 files changed, 7 insertions(+), 1675 deletions(-) diff --git a/.jshintrc b/.jshintrc index a0a9c0ef09..ba217a746a 100644 --- a/.jshintrc +++ b/.jshintrc @@ -1,143 +1,6 @@ /** - * Project specific jshint linting options. - * - * Forked from Airbnb JSHint settings. - * - * @version 0.4.5 - * @source https://github.com/thanpolas/javascript/blob/master/.jshintrc - * @see http://www.jshint.com/docs/ - * @see https://github.com/airbnb/javascript * Forked of Airbnb JSHint settings. - */ -{ - /* - * ENVIRONMENTS - * ================= - */ - - // Define globals exposed by modern browsers. - "browser": false, - - // Define globals exposed by jQuery. - "jquery": false, - - // Define globals exposed by Node.js. - "node": true, - - /* - * TABS AND QUOTES - * ================== - */ - // Enforce tab width of 2 spaces. - "indent": 2, - - // Enforce use of single quotation marks for strings. - "quotmark": "single", - - /* - * ENFORCING OPTIONS - * ================= - */ - - // This option requires you to always put curly braces - // around blocks in loops and conditionals. - "curly": true, - - // This option prohibits the use of immediate function - // invocations without wrapping them in parentheses. - "immed": true, - - // This option prohibits the use of arguments.caller - // and arguments.callee. Both .caller and .callee make - // quite a few optimizations impossible so they were - // deprecated in future versions of JavaScript. - "noarg": true, - - // This option suppresses warnings about the use of - // assignments in cases where comparisons are expected - "boss": true, - - // Force all variable names to use either camelCase style - // or UPPER_CASE with underscores. - "camelcase": true, - - // Prohibit use of == and != in favor of === and !==. - "eqeqeq": true, - - // Suppress warnings about == null comparisons. - "eqnull": true, - - // Prohibit use of a variable before it is defined. - "latedef": true, - - // Require capitalized names for constructor functions. - "newcap": true, - - // Prohibit trailing whitespace. - "trailing": true, - - // Prohibit use of explicitly undeclared variables. - "undef": true, - - // Warn when variables are defined but never used. - "unused": true, - - // do not complain for lack of 'use strict'; - "globalstrict": false, - "strict": false, - - // This option suppresses warnings about the use of expressions where - // normally you would expect to see assignments or function calls. - // Most of the time, such code is a typo. However, it is not forbidden - // by the spec and that's why this warning is optional. - "expr": false, - - // This option suppresses warnings about the use of eval. - // The use of eval is discouraged because it can make your code - // vulnerable to various injection attacks and it makes it hard for - // JavaScript interpreter to do certain optimizations. - "evil": false, - - // This option suppresses warnings about comma-first coding style. - "laxcomma": false, - - // suppress object dot notation warnings, we know what we're doing - "sub": true, - - // This option defines globals that are usually used for logging poor-man's - // debugging: console, alert, etc. It is usually a good idea to not ship - // them in production because, for example, console.log breaks in legacy - // versions of Internet Explorer. - "devel": false, - - // This option suppresses warnings about mixed tabs and spaces when the - // latter are used for alignmnent only. The technique is called SmartTabs. - "smarttabs": false, - - /** - * TEMPORARY OPTIONS - * ================= - * - * These are provisional options for legacy code. - * - */ - - /** - * PROJECT GLOBALS - * ================ - * - */ - "globals": { - /* MOCHA */ - "suite": false, - "test": false, - "describe": false, - "it": false, - "setup": false, - "before": false, - "beforeEach": false, - "after": false, - "afterEach": false, - "teardown": false, - "assert": false - } -} + * THE FILE HAS MOVED TO: + * + * https://github.com/thanpolas/practice/blob/master/.jshintrc + * + */ \ No newline at end of file diff --git a/README.md b/README.md index a3b4b0f1c9..74407b5ad6 100644 --- a/README.md +++ b/README.md @@ -1,1534 +1,3 @@ -# JavaScript Style Guide() { +The Javascript Style Guide -*A mostly reasonable approach to JavaScript* - -Forked from [AirBnB's Javascript repo](https://github.com/airbnb/javascript). - -## Table of Contents - - 1. [Types](#types) - 1. [Objects](#objects) - 1. [Arrays](#arrays) - 1. [Strings](#strings) - 1. [Functions](#functions) - 1. [Properties](#properties) - 1. [Variables](#variables) - 1. [Hoisting](#hoisting) - 1. [Conditional Expressions & Equality](#conditionals) - 1. [Blocks](#blocks) - 1. [Comments](#comments) - 1. [Whitespace](#whitespace) - 1. [Commas](#commas) - 1. [Semicolons](#semicolons) - 1. [Type Casting & Coercion](#type-coercion) - 1. [Naming Conventions](#naming-conventions) - 1. [Accessors](#accessors) - 1. [Constructors](#constructors) - 1. [Events](#events) - 1. [Modules](#modules) - 1. [jQuery](#jquery) - 1. [ES5 Compatibility](#es5) - 1. [Testing](#testing) - 1. [Performance](#performance) - 1. [Resources](#resources) - 1. [In the Wild](#in-the-wild) - 1. [Translation](#translation) - 1. [The JavaScript Style Guide Guide](#guide-guide) - 1. [Contributors](#contributors) - 1. [License](#license) - -## Types - - - **Primitives**: When you access a primitive type you work directly on its value - - + `string` - + `number` - + `boolean` - + `null` - + `undefined` - - ```javascript - var foo = 1; - var bar = foo; - - bar = 9; - - console.log(foo, bar); // => 1, 9 - ``` - - **Complex**: When you access a complex type you work on a reference to its value - - + `object` - + `array` - + `function` - - ```javascript - var foo = [1, 2]; - var bar = foo; - - bar[0] = 9; - - console.log(foo[0], bar[0]); // => 9, 9 - ``` - - **[[⬆]](#TOC)** - -## Objects - - - Use the literal syntax for object creation. - - ```javascript - // bad - var item = new Object(); - - // good - var item = {}; - ``` - - - 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) - - ```javascript - // bad - var superman = { - default: { clark: 'kent' }, - private: true - }; - - // good - var superman = { - defaults: { clark: 'kent' }, - hidden: true - }; - ``` - - - Use readable synonyms in place of reserved words. - - ```javascript - // bad - var superman = { - class: 'alien' - }; - - // bad - var superman = { - klass: 'alien' - }; - - // good - var superman = { - type: 'alien' - }; - ``` - **[[⬆]](#TOC)** - -## Arrays - - - Use the literal syntax for array creation - - ```javascript - // bad - var items = new Array(); - - // good - var items = []; - ``` - - - If you don't know array length use Array#push. - - ```javascript - var someStack = []; - - - // bad - someStack[someStack.length] = 'abracadabra'; - - // good - someStack.push('abracadabra'); - ``` - - - When you need to copy an array use Array#slice. [jsPerf](http://jsperf.com/converting-arguments-to-an-array/7) - - ```javascript - var len = items.length; - var itemsCopy = []; - var i; - - // bad - for (i = 0; i < len; i++) { - itemsCopy[i] = items[i]; - } - - // good - itemsCopy = items.slice(); - ``` - - - To convert an array-like object to an array, use Array#slice. - - ```javascript - function trigger() { - var args = Array.prototype.slice.call(arguments); - ... - } - ``` - - **[[⬆]](#TOC)** - - -## Strings - - - Use single quotes `''` for strings - - ```javascript - // bad - var name = "Bob Parr"; - - // good - var name = 'Bob Parr'; - - // bad - var fullName = "Bob " + this.lastName; - - // good - var fullName = 'Bob ' + this.lastName; - ``` - - - Strings longer than 80 characters should be written across multiple lines using string concatenation. - - 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) - - ```javascript - // bad - 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.'; - - // bad - 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.'; - - - // good - 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.'; - ``` - - - When programatically building up a string, use Array#join instead of string concatenation. Mostly for IE: [jsPerf](http://jsperf.com/string-vs-array-concat/2). - - ```javascript - var items; - var messages; - var length; - var i; - - messages = [{ - state: 'success', - message: 'This one worked.' - }, { - state: 'success', - message: 'This one worked as well.' - }, { - state: 'error', - message: 'This one did not work.' - }]; - - length = messages.length; - - // bad - function inbox(messages) { - items = '
    '; - - for (i = 0; i < length; i++) { - items += '
  • ' + messages[i].message + '
  • '; - } - - return items + '
'; - } - - // good - function inbox(messages) { - items = []; - - for (i = 0; i < length; i++) { - items[i] = messages[i].message; - } - - return '
  • ' + items.join('
  • ') + '
'; - } - ``` - - **[[⬆]](#TOC)** - - -## Functions - - - Function expressions: - - ```javascript - // anonymous function expression - var anonymous = function() { - return true; - }; - - // named function expression - var named = function named() { - return true; - }; - - // immediately-invoked function expression (IIFE) - (function() { - console.log('Welcome to the Internet. Please follow me.'); - })(); - ``` - - - 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. - - **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). - - ```javascript - // bad - if (currentUser) { - function test() { - console.log('Nope.'); - } - } - - // good - var test; - if (currentUser) { - test = function test() { - console.log('Yup.'); - }; - } - ``` - - - Never name a parameter `arguments`, this will take precedence over the `arguments` object that is given to every function scope. - - ```javascript - // bad - function nope(name, options, arguments) { - // ...stuff... - } - - // good - function yup(name, options, args) { - // ...stuff... - } - ``` - - **[[⬆]](#TOC)** - - - -## Properties - - - Use dot notation when accessing properties. - - ```javascript - var luke = { - jedi: true, - age: 28 - }; - - // bad - var isJedi = luke['jedi']; - - // good - var isJedi = luke.jedi; - ``` - - - Use subscript notation `[]` when accessing properties with a variable. - - ```javascript - var luke = { - jedi: true, - age: 28 - }; - - function getProp(prop) { - return luke[prop]; - } - - var isJedi = getProp('jedi'); - ``` - - **[[⬆]](#TOC)** - - -## Variables - - - 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. - - ```javascript - // bad - superPower = new SuperPower(); - - // good - var superPower = new SuperPower(); - ``` - - - Use multiple `var` declarations for multiple variables and declare each variable on a newline. - - ```javascript - // bad - var items = getItems(), - goSportsTeam = true, - dragonball = 'z'; - - // good - var items = getItems(); - var goSportsTeam = true; - var dragonball = 'z'; - - ``` - - - Assign variables at the top of their scope. This helps avoid issues with variable declaration and assignment hoisting related issues. - - ```javascript - // bad - function() { - test(); - console.log('doing stuff..'); - - //..other stuff.. - - var name = getName(); - - if (name === 'test') { - return false; - } - - return name; - } - - // good - function() { - var name = getName(); - - test(); - console.log('doing stuff..'); - - //..other stuff.. - - if (name === 'test') { - return false; - } - - return name; - } - - // bad - function() { - var name = getName(); - - if (!arguments.length) { - return false; - } - - return true; - } - - // good - function() { - if (!arguments.length) { - return false; - } - - var name = getName(); - - return true; - } - ``` - - **[[⬆]](#TOC)** - - -## Hoisting - - - Variable declarations get hoisted to the top of their scope, their assignment does not. - - ```javascript - // we know this wouldn't work (assuming there - // is no notDefined global variable) - function example() { - console.log(notDefined); // => throws a ReferenceError - } - - // creating a variable declaration after you - // reference the variable will work due to - // variable hoisting. Note: the assignment - // value of `true` is not hoisted. - function example() { - console.log(declaredButNotAssigned); // => undefined - var declaredButNotAssigned = true; - } - - // The interpreter is hoisting the variable - // declaration to the top of the scope. - // Which means our example could be rewritten as: - function example() { - var declaredButNotAssigned; - console.log(declaredButNotAssigned); // => undefined - declaredButNotAssigned = true; - } - ``` - - - Anonymous function expressions hoist their variable name, but not the function assignment. - - ```javascript - function example() { - console.log(anonymous); // => undefined - - anonymous(); // => TypeError anonymous is not a function - - var anonymous = function() { - console.log('anonymous function expression'); - }; - } - ``` - - - Named function expressions hoist the variable name, not the function name or the function body. - - ```javascript - function example() { - console.log(named); // => undefined - - named(); // => TypeError named is not a function - - superPower(); // => ReferenceError superPower is not defined - - var named = function superPower() { - console.log('Flying'); - }; - } - - // the same is true when the function name - // is the same as the variable name. - function example() { - console.log(named); // => undefined - - named(); // => TypeError named is not a function - - var named = function named() { - console.log('named'); - } - } - ``` - - - Function declarations hoist their name and the function body. - - ```javascript - function example() { - superPower(); // => Flying - - function superPower() { - console.log('Flying'); - } - } - ``` - - - 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/) - - **[[⬆]](#TOC)** - - - -## Conditional Expressions & Equality - - - Use `===` and `!==` over `==` and `!=`. - - Always use the testing part first and the expected value second: - - '''javascript - // bad - if (2 === values.length) {} - - // good - if (values.length === 2) {} - ``` - - - Conditional expressions are evaluated using coercion with the `ToBoolean` method and always follow these simple rules: - - + **Objects** evaluate to **true** - + **Undefined** evaluates to **false** - + **Null** evaluates to **false** - + **Booleans** evaluate to **the value of the boolean** - + **Numbers** evaluate to **false** if **+0, -0, or NaN**, otherwise **true** - + **Strings** evaluate to **false** if an empty string `''`, otherwise **true** - - ```javascript - if ([0]) { - // true - // An array is an object, objects evaluate to true - } - ``` - - - Use shortcuts. - - ```javascript - // bad - if (name !== '') { - // ...stuff... - } - - // good - if (name) { - // ...stuff... - } - - // bad - if (collection.length > 0) { - // ...stuff... - } - - // good - if (collection.length) { - // ...stuff... - } - ``` - - - For more information see [Truth Equality and JavaScript](http://javascriptweblog.wordpress.com/2011/02/07/truth-equality-and-javascript/#more-2108) by Angus Croll - - **[[⬆]](#TOC)** - - -## Blocks - - - Use braces with all multi-line blocks. - - ```javascript - // bad - if (test) - return false; - - // good - if (test) return false; - - // good - if (test) { - return false; - } - - // bad - function() { return false; } - - // good - function() { - return false; - } - ``` - - **[[⬆]](#TOC)** - - -## Comments - - - Use `/** ... */` for multiline comments. Include a description, specify types and values for all parameters and return values. - - ```javascript - // bad - // make() returns a new element - // based on the passed in tag name - // - // @param tag - // @return element - function make(tag) { - - // ...stuff... - - return element; - } - - // good - /** - * make() returns a new element - * based on the passed in tag name - * - * @param tag - * @return element - */ - function make(tag) { - - // ...stuff... - - return element; - } - ``` - - - 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. - - ```javascript - // bad - var active = true; // is current tab - - // good - // is current tab - var active = true; - - // bad - function getType() { - console.log('fetching type...'); - // set the default type to 'no type' - var type = this._type || 'no type'; - - return type; - } - - // good - function getType() { - console.log('fetching type...'); - - // set the default type to 'no type' - var type = this._type || 'no type'; - - return type; - } - ``` - - - 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`. - - - Use `// FIXME:` to annotate problems - - ```javascript - function Calculator() { - - // FIXME: shouldn't use a global here - total = 0; - - return this; - } - ``` - - - Use `// TODO:` to annotate solutions to problems - - ```javascript - function Calculator() { - - // TODO: total should be configurable by an options param - this.total = 0; - - return this; - } - ``` - - **[[⬆]](#TOC)** - - -## Whitespace - - - Use soft tabs set to 2 spaces - - ```javascript - // bad - function() { - ∙∙∙∙var name; - } - - // bad - function() { - ∙var name; - } - - // good - function() { - ∙∙var name; - } - ``` - - - Place 1 space before the leading brace. - - ```javascript - // bad - function test(){ - console.log('test'); - } - - // good - function test() { - console.log('test'); - } - - // bad - dog.set('attr',{ - age: '1 year', - breed: 'Bernese Mountain Dog' - }); - - // good - dog.set('attr', { - age: '1 year', - breed: 'Bernese Mountain Dog' - }); - ``` - - - Set off operators with spaces. - - ```javascript - // bad - var x=y+5; - - // good - var x = y + 5; - ``` - - - Place an empty newline at the end of the file. - - ```javascript - // bad - (function(global) { - // ...stuff... - })(this); - ``` - - ```javascript - // good - (function(global) { - // ...stuff... - })(this); - - ``` - - - Use indentation when making long method chains. - - ```javascript - // bad - $('#items').find('.selected').highlight().end().find('.open').updateCount(); - - // good - $('#items') - .find('.selected') - .highlight() - .end() - .find('.open') - .updateCount(); - - // bad - var leds = stage.selectAll('.led').data(data).enter().append('svg:svg').class('led', true) - .attr('width', (radius + margin) * 2).append('svg:g') - .attr('transform', 'translate(' + (radius + margin) + ',' + (radius + margin) + ')') - .call(tron.led); - - // good - var leds = stage.selectAll('.led') - .data(data) - .enter().append('svg:svg') - .class('led', true) - .attr('width', (radius + margin) * 2) - .append('svg:g') - .attr('transform', 'translate(' + (radius + margin) + ',' + (radius + margin) + ')') - .call(tron.led); - ``` - - **[[⬆]](#TOC)** - -## Commas - - - Leading commas: **Nope.** - - ```javascript - // bad - var once - , upon - , aTime; - - // good - var once, - upon, - aTime; - - // bad - var hero = { - firstName: 'Bob' - , lastName: 'Parr' - , heroName: 'Mr. Incredible' - , superPower: 'strength' - }; - - // good - var hero = { - firstName: 'Bob', - lastName: 'Parr', - heroName: 'Mr. Incredible', - superPower: 'strength' - }; - ``` - - - Additional trailing comma: **Yeap** for Node.js **Nope** for Browsers, 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)): - - > 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. - - ```javascript - // bad - var hero = { - firstName: 'Kevin', - lastName: 'Flynn', - }; - - var heroes = [ - 'Batman', - 'Superman', - ]; - - // good - var hero = { - firstName: 'Kevin', - lastName: 'Flynn' - }; - - var heroes = [ - 'Batman', - 'Superman' - ]; - ``` - - **[[⬆]](#TOC)** - - -## Semicolons - - - **Yup.** - - ```javascript - // bad - (function() { - var name = 'Skywalker' - return name - })() - - // good - (function() { - var name = 'Skywalker'; - return name; - })(); - - // good - ;(function() { - var name = 'Skywalker'; - return name; - })(); - ``` - - **[[⬆]](#TOC)** - - -## Type Casting & Coercion - - - Perform type coercion at the beginning of the statement. - - Strings: - - ```javascript - // => this.reviewScore = 9; - - // bad - var totalScore = this.reviewScore + ''; - - // good - var totalScore = '' + this.reviewScore; - - // bad - var totalScore = '' + this.reviewScore + ' total score'; - - // good - var totalScore = this.reviewScore + ' total score'; - ``` - - - Use `parseInt` for Numbers and always with a radix for type casting. - - ```javascript - var inputValue = '4'; - - // bad - var val = new Number(inputValue); - - // bad - var val = +inputValue; - - // bad - var val = inputValue >> 0; - - // bad - var val = parseInt(inputValue); - - // good - var val = Number(inputValue); - - // good - var val = parseInt(inputValue, 10); - ``` - - - 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. - - **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) - - ```javascript - // good - /** - * parseInt was the reason my code was slow. - * Bitshifting the String to coerce it to a - * Number made it a lot faster. - */ - var val = inputValue >> 0; - ``` - - - Booleans: - - ```javascript - var age = 0; - - // bad - var hasAge = new Boolean(age); - - // good - var hasAge = Boolean(age); - - // good - var hasAge = !!age; - ``` - - **[[⬆]](#TOC)** - - -## Naming Conventions - - - Avoid single letter names. Be descriptive with your naming. - - ```javascript - // bad - function q() { - // ...stuff... - } - - // good - function query() { - // ..stuff.. - } - ``` - - - Use camelCase when naming objects, functions, and instances - - ```javascript - // bad - var OBJEcttsssss = {}; - var this_is_my_object = {}; - function c() {}; - var u = new user({ - name: 'Bob Parr' - }); - - // good - var thisIsMyObject = {}; - function thisIsMyFunction() {}; - var user = new User({ - name: 'Bob Parr' - }); - ``` - - - Use PascalCase when naming constructors or classes - - ```javascript - // bad - function user(options) { - this.name = options.name; - } - - var bad = new user({ - name: 'nope' - }); - - // good - function User(options) { - this.name = options.name; - } - - var good = new User({ - name: 'yup' - }); - ``` - - - Use a leading underscore `_` when naming private properties - - ```javascript - // bad - this.__firstName__ = 'Panda'; - this.firstName_ = 'Panda'; - - // good - this._firstName = 'Panda'; - ``` - - - When saving a reference to `this` use `_this`. - - ```javascript - // bad - function() { - var self = this; - return function() { - console.log(self); - }; - } - - // bad - function() { - var that = this; - return function() { - console.log(that); - }; - } - - // good - function() { - var _this = this; - return function() { - console.log(_this); - }; - } - ``` - - - Name your functions. This is helpful for stack traces. - - ```javascript - // bad - var log = function(msg) { - console.log(msg); - }; - - // good - var log = function log(msg) { - console.log(msg); - }; - ``` - - **[[⬆]](#TOC)** - - -## Accessors - - - Accessor functions for properties are not required - - If you do make accessor functions use getVal() and setVal('hello') - - ```javascript - // bad - dragon.age(); - - // good - dragon.getAge(); - - // bad - dragon.age(25); - - // good - dragon.setAge(25); - ``` - - - If the property is a boolean, use isVal() or hasVal() - - ```javascript - // bad - if (!dragon.age()) { - return false; - } - - // good - if (!dragon.hasAge()) { - return false; - } - ``` - - - It's okay to create get() and set() functions, but be consistent. - - ```javascript - function Jedi(options) { - options || (options = {}); - var lightsaber = options.lightsaber || 'blue'; - this.set('lightsaber', lightsaber); - } - - Jedi.prototype.set = function(key, val) { - this[key] = val; - }; - - Jedi.prototype.get = function(key) { - return this[key]; - }; - ``` - - **[[⬆]](#TOC)** - - -## Constructors - - - 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! - - ```javascript - function Jedi() { - console.log('new jedi'); - } - - // bad - Jedi.prototype = { - fight: function fight() { - console.log('fighting'); - }, - - block: function block() { - console.log('blocking'); - } - }; - - // good - Jedi.prototype.fight = function fight() { - console.log('fighting'); - }; - - Jedi.prototype.block = function block() { - console.log('blocking'); - }; - ``` - - - Methods can return `this` to help with method chaining. - - ```javascript - // bad - Jedi.prototype.jump = function() { - this.jumping = true; - return true; - }; - - Jedi.prototype.setHeight = function(height) { - this.height = height; - }; - - var luke = new Jedi(); - luke.jump(); // => true - luke.setHeight(20) // => undefined - - // good - Jedi.prototype.jump = function() { - this.jumping = true; - return this; - }; - - Jedi.prototype.setHeight = function(height) { - this.height = height; - return this; - }; - - var luke = new Jedi(); - - luke.jump() - .setHeight(20); - ``` - - - - It's okay to write a custom toString() method, just make sure it works successfully and causes no side effects. - - ```javascript - function Jedi(options) { - options || (options = {}); - this.name = options.name || 'no name'; - } - - Jedi.prototype.getName = function getName() { - return this.name; - }; - - Jedi.prototype.toString = function toString() { - return 'Jedi - ' + this.getName(); - }; - ``` - - **[[⬆]](#TOC)** - - -## Events - - - 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: - - ```js - // bad - $(this).trigger('listingUpdated', listing.id); - - ... - - $(this).on('listingUpdated', function(e, listingId) { - // do something with listingId - }); - ``` - - prefer: - - ```js - // good - $(this).trigger('listingUpdated', { listingId : listing.id }); - - ... - - $(this).on('listingUpdated', function(e, data) { - // do something with data.listingId - }); - ``` - - **[[⬆]](#TOC)** - - -## Modules - - - 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) - - The file should be named with camelCase, live in a folder with the same name, and match the name of the single export. - - Add a method called noConflict() that sets the exported module to the previous version and returns this one. - - Do not use `'use strict';` at the top of the module! - - ```javascript - // fancyInput/fancyInput.js - - !function(global) { - - var previousFancyInput = global.FancyInput; - - function FancyInput(options) { - this.options = options || {}; - } - - FancyInput.noConflict = function noConflict() { - global.FancyInput = previousFancyInput; - return FancyInput; - }; - - global.FancyInput = FancyInput; - }(this); - ``` - - **[[⬆]](#TOC)** - - -## jQuery - - - Prefix jQuery object variables with a `$`. - - ```javascript - // bad - var sidebar = $('.sidebar'); - - // good - var $sidebar = $('.sidebar'); - ``` - - - Cache jQuery lookups. - - ```javascript - // bad - function setSidebar() { - $('.sidebar').hide(); - - // ...stuff... - - $('.sidebar').css({ - 'background-color': 'pink' - }); - } - - // good - function setSidebar() { - var $sidebar = $('.sidebar'); - $sidebar.hide(); - - // ...stuff... - - $sidebar.css({ - 'background-color': 'pink' - }); - } - ``` - - - For DOM queries use Cascading `$('.sidebar ul')` or parent > child `$('.sidebar > ul')`. [jsPerf](http://jsperf.com/jquery-find-vs-context-sel/16) - - Use `find` with scoped jQuery object queries. - - ```javascript - // bad - $('ul', '.sidebar').hide(); - - // bad - $('.sidebar').find('ul').hide(); - - // good - $('.sidebar ul').hide(); - - // good - $('.sidebar > ul').hide(); - - // good - $sidebar.find('ul').hide(); - ``` - - **[[⬆]](#TOC)** - - -## ECMAScript 5 Compatibility - - - Refer to [Kangax](https://twitter.com/kangax/)'s ES5 [compatibility table](http://kangax.github.com/es5-compat-table/) - - **[[⬆]](#TOC)** - - -## Testing - - - **Yup.** - - ```javascript - function() { - return true; - } - ``` - - **[[⬆]](#TOC)** - - -## Performance - - - [On Layout & Web Performance](http://kellegous.com/j/2013/01/26/layout-performance/) - - [String vs Array Concat](http://jsperf.com/string-vs-array-concat/2) - - [Try/Catch Cost In a Loop](http://jsperf.com/try-catch-in-loop-cost) - - [Bang Function](http://jsperf.com/bang-function) - - [jQuery Find vs Context, Selector](http://jsperf.com/jquery-find-vs-context-sel/13) - - [innerHTML vs textContent for script text](http://jsperf.com/innerhtml-vs-textcontent-for-script-text) - - [Long String Concatenation](http://jsperf.com/ya-string-concat) - - Loading... - - **[[⬆]](#TOC)** - - -## Resources - - -**Read This** - - - [Annotated ECMAScript 5.1](http://es5.github.com/) - -**Other Styleguides** - - - [Google JavaScript Style Guide](http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml) - - [jQuery Core Style Guidelines](http://docs.jquery.com/JQuery_Core_Style_Guidelines) - - [Principles of Writing Consistent, Idiomatic JavaScript](https://github.com/rwldrn/idiomatic.js/) - -**Other Styles** - - - [Naming this in nested functions](https://gist.github.com/4135065) - Christian Johansen - - [Conditional Callbacks](https://github.com/airbnb/javascript/issues/52) - - [Popular JavaScript Coding Conventions on Github](http://sideeffect.kr/popularconvention/#javascript) - -**Further Reading** - - - [Understanding JavaScript Closures](http://javascriptweblog.wordpress.com/2010/10/25/understanding-javascript-closures/) - Angus Croll - - [Basic JavaScript for the impatient programmer](http://www.2ality.com/2013/06/basic-javascript.html) - Dr. Axel Rauschmayer - - [You Might Not Need jQuery](http://youmightnotneedjquery.com/) - Zack Bloom & Adam Schwartz - -**Books** - - - [JavaScript: The Good Parts](http://www.amazon.com/JavaScript-Good-Parts-Douglas-Crockford/dp/0596517742) - Douglas Crockford - - [JavaScript Patterns](http://www.amazon.com/JavaScript-Patterns-Stoyan-Stefanov/dp/0596806752) - Stoyan Stefanov - - [Pro JavaScript Design Patterns](http://www.amazon.com/JavaScript-Design-Patterns-Recipes-Problem-Solution/dp/159059908X) - Ross Harmes and Dustin Diaz - - [High Performance Web Sites: Essential Knowledge for Front-End Engineers](http://www.amazon.com/High-Performance-Web-Sites-Essential/dp/0596529309) - Steve Souders - - [Maintainable JavaScript](http://www.amazon.com/Maintainable-JavaScript-Nicholas-C-Zakas/dp/1449327680) - Nicholas C. Zakas - - [JavaScript Web Applications](http://www.amazon.com/JavaScript-Web-Applications-Alex-MacCaw/dp/144930351X) - Alex MacCaw - - [Pro JavaScript Techniques](http://www.amazon.com/Pro-JavaScript-Techniques-John-Resig/dp/1590597273) - John Resig - - [Smashing Node.js: JavaScript Everywhere](http://www.amazon.com/Smashing-Node-js-JavaScript-Everywhere-Magazine/dp/1119962595) - Guillermo Rauch - - [Secrets of the JavaScript Ninja](http://www.amazon.com/Secrets-JavaScript-Ninja-John-Resig/dp/193398869X) - John Resig and Bear Bibeault - - [Human JavaScript](http://humanjavascript.com/) - Henrik Joreteg - - [Superhero.js](http://superherojs.com/) - Kim Joar Bekkelund, Mads Mobæk, & Olav Bjorkoy - - [JSBooks](http://jsbooks.revolunet.com/) - - [Third Party JavaScript](http://manning.com/vinegar/) - Ben Vinegar and Anton Kovalyov - -**Blogs** - - - [DailyJS](http://dailyjs.com/) - - [JavaScript Weekly](http://javascriptweekly.com/) - - [JavaScript, JavaScript...](http://javascriptweblog.wordpress.com/) - - [Bocoup Weblog](http://weblog.bocoup.com/) - - [Adequately Good](http://www.adequatelygood.com/) - - [NCZOnline](http://www.nczonline.net/) - - [Perfection Kills](http://perfectionkills.com/) - - [Ben Alman](http://benalman.com/) - - [Dmitry Baranovskiy](http://dmitry.baranovskiy.com/) - - [Dustin Diaz](http://dustindiaz.com/) - - [nettuts](http://net.tutsplus.com/?s=javascript) - - **[[⬆]](#TOC)** - -## In the Wild - - 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. - - - **Aan Zee**: [AanZee/javascript](https://github.com/AanZee/javascript) - - **Airbnb**: [airbnb/javascript](https://github.com/airbnb/javascript) - - **American Insitutes for Research**: [AIRAST/javascript](https://github.com/AIRAST/javascript) - - **Compass Learning**: [compasslearning/javascript-style-guide](https://github.com/compasslearning/javascript-style-guide) - - **ExactTarget**: [ExactTarget/javascript](https://github.com/ExactTarget/javascript) - - **Gawker Media**: [gawkermedia/javascript](https://github.com/gawkermedia/javascript) - - **GeneralElectric**: [GeneralElectric/javascript](https://github.com/GeneralElectric/javascript) - - **GoodData**: [gooddata/gdc-js-style](https://github.com/gooddata/gdc-js-style) - - **Grooveshark**: [grooveshark/javascript](https://github.com/grooveshark/javascript) - - **How About We**: [howaboutwe/javascript](https://github.com/howaboutwe/javascript) - - **Mighty Spring**: [mightyspring/javascript](https://github.com/mightyspring/javascript) - - **MinnPost**: [MinnPost/javascript](https://github.com/MinnPost/javascript) - - **ModCloth**: [modcloth/javascript](https://github.com/modcloth/javascript) - - **National Geographic**: [natgeo/javascript](https://github.com/natgeo/javascript) - - **National Park Service**: [nationalparkservice/javascript](https://github.com/nationalparkservice/javascript) - - **Peerby**: [Peerby/javascript](https://github.com/Peerby/javascript) - - **Razorfish**: [razorfish/javascript-style-guide](https://github.com/razorfish/javascript-style-guide) - - **REI**: [reidev/js-style-guide](https://github.com/reidev/js-style-guide) - - **Shutterfly**: [shutterfly/javascript](https://github.com/shutterfly/javascript) - - **Userify**: [userify/javascript](https://github.com/userify/javascript) - - **Zillow**: [zillow/javascript](https://github.com/zillow/javascript) - - **ZocDoc**: [ZocDoc/javascript](https://github.com/ZocDoc/javascript) - -## Translation - - This style guide is also available in other languages: - - - :de: **German**: [timofurrer/javascript-style-guide](https://github.com/timofurrer/javascript-style-guide) - - :jp: **Japanese**: [mitsuruog/javacript-style-guide](https://github.com/mitsuruog/javacript-style-guide) - - :br: **Portuguese**: [armoucar/javascript-style-guide](https://github.com/armoucar/javascript-style-guide) - - :cn: **Chinese**: [adamlu/javascript-style-guide](https://github.com/adamlu/javascript-style-guide) - - :es: **Spanish**: [paolocarrasco/javascript-style-guide](https://github.com/paolocarrasco/javascript-style-guide) - - :kr: **Korean**: [tipjs/javascript-style-guide](https://github.com/tipjs/javascript-style-guide) - - :fr: **French**: [nmussy/javascript-style-guide](https://github.com/nmussy/javascript-style-guide) - - :ru: **Russian**: [uprock/javascript](https://github.com/uprock/javascript) - - :bg: **Bulgarian**: [borislavvv/javascript](https://github.com/borislavvv/javascript) - -## The JavaScript Style Guide Guide - - - [Reference](https://github.com/airbnb/javascript/wiki/The-JavaScript-Style-Guide-Guide) - -## Contributors - - - [View Contributors](https://github.com/airbnb/javascript/graphs/contributors) - - -## License - -(The MIT License) - -Copyright (c) 2014 Airbnb - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -**[[⬆]](#TOC)** - -# }; +# [Has moved to the practice repository](https://github.com/thanpolas/Practice/blob/master/Javascript-Style-Guide.md) \ No newline at end of file