Code Monkey home page Code Monkey logo

code-guide's People

Contributors

jaymcp avatar markgoodyear avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Forkers

dgtouch xavierfox

code-guide's Issues

Objects: Prototype Extension

Never extend the prototype of native objects, or overwrite native object properties.
(I stole the below example from somewhere)

var a = [];
if (!a.length) {
  console.log('a is empty');
}

// not

Array.prototype.empty = function () {
  return !this.length;
}

var a = [];

if (a.empty()) {
console.log('a is empty');
}

Functions: return values

This is perhaps moreso for library-based code than otherwise; should we recommend returning an object, where possible, to allow method chaining?

Functions: Parentheses

How's aboot this?

You must leave a space before and after function parentheses:
function foo () {} not function foo(){}
In an IIFE, it's okay not to space before & after the invokation parens; however, the declaration parens must still have the sapces:

(function () {
    // do stuff
}());

Arrays: looping through members

Not wholly sold on this one, but it is something that I do. Thoughts?

It is preferred to use ES5 array loops, where applicable:

theArray.forEach(function (value, index) {
    newArr.push([index, value]);
});

// instead of 
var newArr = [],
      i;

for (i = 0; i < theArray.length; i++) {
    newArr[i] = [i, theArray[i]];
}

This is not a hard-and-fast rule, as there are valid use-cases for the latter method, but the former is much more semantic when applicable.

Objects: looping through member properties

When performing object loops, you must wrap the loop body in an if statement, to check that the current property is a member of the subject, and not an inherited property:

// function body
var prop;

for (prop in theObject) {
    if (theObject.hasOwnProperty(prop)) {
        // logic
    }
}

jQuery: Document Ready

To the best of my knowledge, there is literally no point in the jQuery Document Ready function $(document).ready(function () {}); or $(function () {});; we always include our scripts in the footer so, by the time the script is parsed, the document is already fully parsed.
Since we've already agreed to wrap our code in an IIFE, anyway, I feel it would be more prudent to simply pass jQuery as an argument to that (which we probably would anyway).

NB:
Please don't confuse this with the jQuery $(window).load(function () {}); methodology - this event uses the window's (on)load event, not DOMContentLoaded. This API method can safely be wrapped inside of the IIFE.

General: Equality

Always use strict (in)equality operators.

a === b;
c !== d;

// not

a == b;
c != d;

Events: Binding Data to Events

When passing data to an event, pass an object, rather than a value; passing an object allows additional data to be added at a later date. i.e.

// pseudo code

// do this
var.fire('eventName', { item: value });
var.listen('eventName', function (event, data) {
  // do something with `data.item`
});

// not this
var.fire('eventName', value);
var.listen('eventName', function (event, value) {
  // do something with value
});

Objects: Adding Properties to Constructors

Adding properties to an object by overwriting the prototype makes inheritance impossible; appending to a prototype means that all properties inherited from the parent are still accessible to the child (unless you're purposely overwriting a property -> something you shouldn't do, anyway, except in rare cases!).

function BigBite () {
  console.log('foo');
}

// overwriting prototype
BigBite.prototype = {
  staff: ['jason', 'mark', 'iain', 'natalie'],

  addMember: function (name) {
    this.staff.push(name);
  }
};

// appending to prototype
BigBite.prototype.staff = ['jason', 'mark', 'iain', 'natalie'];
BigBite.prototype.addMember = function (name) {
  this.staff.push(name);
};

General: for statements

I'm an option two kinda guy.

// option one
var len = thing.length;
var i;

for (i = 0; i < len; i++) {
  // do stuff
}

// option two
var len = thing.length;
var i   = 0;

for (i; i < len; i++) {
  // do stuff
}

// option 3
var len = thing.length;
var i   = 0;

for ( ; i < len; i++) {
  // do stuff
}

General: Encapsulation

For projects not involving Angular, (i.e. WP projects), since Angular provides its own method of encapsulation, I propose wrapping code blocks in an IIFE; thoughts?

/*
 * This is an Immediately-Invoked Function Expression, or IIFE.
 * Wrapping code inside an IIFE provides encapsulation, so that
 * the global scope is protected from pollution. Additionally,
 * it provents naming collision between code blocks.
 * Arguments listed within the function parentheses are passed
 * in at the end of the expression.
 */
(function (win, doc, $) {

    //code goes here

}(window, document, jQuery));
/*
 * Any arguments to be passed to the function scope should be
 * added within the parentheses after the closing curly brace.
 * When jQuery is in use, pass the no-conflict variant of the
 * `jQuery` object, rather than the `$` shorthand. `$` can be
 * specified as the function parameter at the start of the
 * expression.
 * Passing `window` and `document` as parameters increases
 * performance by saving lookups.
 */

UnderscoreJS

If the project isn't using Angular or another framework then I think projects should include UnderscoreJS as standard as it helps a lot when working Arrays.

http://underscorejs.org/

General: Argument lists

If arguments supplied (whether it be to a conditional or a function) result in large line lengths, it can be more readable to introduce line breaks. Which would be your preferred method:

// option zero
if (conditionOne() && conditionTwo() && conditionThree() && reallyLongConditionFourThatTakesUpALotOfSpace()) {
}

// option one
if (conditionOne() && conditionTwo() && conditionThree() &&
    reallyLongConditionFourThatTakesUpALotOfSpace()) {
}

// option two
if (conditionOne() &&
    conditionTwo() &&
    conditionThree() &&
    reallyLongConditionFourThatTakesUpALotOfSpace()) {
}

// option three
if (conditionOne() &&
    conditionTwo() &&
    conditionThree() &&
    reallyLongConditionFourThatTakesUpALotOfSpace()
) {
}

// option four
if (
  conditionOne() &&
  conditionTwo() &&
  conditionThree() &&
  reallyLongConditionFourThatTakesUpALotOfSpace()
) {
}

// option five
if (
  conditionOne() &&
  conditionTwo() &&
  conditionThree() &&
  reallyLongConditionFourThatTakesUpALotOfSpace()) {
}

Functions: Named Function Expressions

Similar topic to #19:

var foo = function (val) {
  // stuff
};

// vs

var foo = function foo (val) {
  // stuff
};

Purportedly easier for stack traces. Going to run some tests for both this and #19.

More variables

variable naming

Variable names should always be in lowerCamelCase, except in two instances:

  1. classes, which should be in UpperCamelCase
  2. constants, which should be in CAPS_SNAKE_CASE

variable assignment

Boolean vars should be set to true or false, don't use 1 and 0 unless you have good reason to
When intentionally setting/removing a value, you should set it to null
Never set values as undefined

Configs

We need a folder created for stuff like .editorconfig that follows this style guide.

Functions: Closures

I've just seen something on this, and it seems like a cool idea; going to have to try testing it.
Apparently one can have named closures:

var a = [a, b, c];
a.forEach(function loopy (v, i) {
  // oooh, fancy
});

Variable instantiation

Variables should be instantiated using literal over constructor notation, in my opinion:

var scopeObjVar  = {},    // empty object
    scopeArrVar  = [];    // empty array

// instead of 

var scopeObjVar = new Object(),
    scopeArrVar = new Array();

General: Docblocks

All functions should be preceded by a docblock comment describing the function logic, its parameters, and its return value (if any).

/**
 * grabs the header, does some funky stuff with it, and returns the object
 * @param  {jQuery object} selector the selector upon which we're performing logic
 * @return {jQuery object}          the selector in its new state
 */
function doSomething (selector) {
    selector = selector || $('#header');

    selector.height(50)
            .width(60)
            .addClass('sexy')
            .fadeOut();

    return selector;
}

General: Curly braces

When using curly braces, always open them on the same line as the statement.

function foo () {
  // something
}

// not

function foo ()
{
  // something
}

Functions: Method chaining with callbacks

Here's a few different variations on a theme; it's an angular snippet, but it applies to any javascript. which is your preference?

angular.module('app')
  .controller('AccountController', function ($scope, $state) {
    $scope.stateData = $state.current.data;
  });

angular
  .module('app')
  .controller('AccountController', function ($scope, $state) {
    $scope.stateData = $state.current.data;
  });

angular
.module('app')
.controller('AccountController', function ($scope, $state) {
  $scope.stateData = $state.current.data;
});

angular.module('app')
  .controller('AccountController',
    function ($scope, $state) {
      $scope.stateData = $state.current.data;
    }
  );

angular.module('app')
  .controller(
    'AccountController',
    function ($scope, $state) {
      $scope.stateData = $state.current.data;
    }
  );

angular
.module('app')
.controller(
  'AccountController',
  function ($scope, $state) {
    $scope.stateData = $state.current.data;
  }
);

General: Comments

Multi line comments should use the /* ... */ syntax; single line comments should use the // ... syntax.

// single line comment
/*
 * multi line comment.
 * ooh, this is nice
 */

// instead of

/* what am i doing, why am i doing it? */
// hey,
// this is a multi line comment
// look at how silly i look

Functions: Dependency inversion

Functions should not, where possible, be bound to specifics. Instead, they should perform logic upon parameters passed to the function.

/**
 * grabs the header, does some funky stuff with it, and returns the object
 * @param  {jQuery object} selector the selector upon which we're performing logic
 * @return {jQuery object}          the selector in its new state
 */
function doSomething (selector) {
    selector = selector || $('#header');

    ...
}

// instead of

function doSomething () {
    var selector =  $('#header');

    ...
}

Functions: Strict Pragma

the 'use strict'; declaration must be used in the topmost level of function hierarchy. In many cases, this will be the first line of the IIFE body:

(function (win, doc) {
    'use strict';

    function doSomething () {
    }

    function doSomethingElse () {
    }
}(window, document));

Variables: 'Private' vars

Should we prefix private variables with _? It's a convention some people use (I have, myself, in the past), but I'm neither for or against it.

Douglass Crockford (the dude who developed JSON & jslint.com) recommends against it, since there's no real privacy in JS, and it could be misleading.
Companies like airbnb recommend using it.

Thoughts?

jQuery: Selectors

What do you think about this?

When using jQuery selectors, you should assign them to variables:

function doSomething () {
    var $header  = $('#header'),
        $nav     = $('#main-nav'),
        $content = $('#content'),
        offset   = $header.outerHeight(false) + $nav.outerHeight(false);

    return $content.css({ marginTop : offset });
}

Doing this allows you to use a selector repeatedly without having to re-query the DOM; it also provides a meaningful naming convention in JavaScript should the selector be ambiguous (though it shouldn't be!)

General: Argument spacing

You should not add whitespace between parens and arguments. You should space between comma-separated arguments.

// do this
function doSomething (arg, arg2) {
  // stuff
}
doSomething(arg, arg2);

// not this
function doSomething ( arg, arg2 ) {
  // stuff
}
doSomething( arg, arg2 );

// or this
function doSomething ( arg,arg2 ) {
  // stuff
}
doSomething( arg,arg2 );

Objects: Accessing Object Properties

Object properties must be accessed using dot notation when the property being accessed is not dynamic:

var schema = {
    revenue: {
        indexes: [0.01, 1.00, 2.50, 5.00, 100.00],
        colours: ['#bebebf', '#AADAE1', '#92E5E8', '#54D5D9', '#408F98'],
        labels:  ['0% of revenue', '<1% of revenue', '<2.5% of revenue', '<5% of revenue', '5%+ of revenue']
    }
};

// like this
console.log(schema.revenue.indexes);

// instead of
console.log(schema[revenue][indexes]);

Bracket notation should only be used when accessing properties via a variable.

Objects: OOJS Method Chaining

I do this.

When method chaining, you should break each method in the chain onto a new line, and align the periods:

function doSomething () {
    var $header = $('#header');

    $header.height(50)
           .width(60)
           .addClass('sexy')
           .fadeOut();

    return $header;
}

Variable declarations

One:

var one   = 'one';
var two   = 'two';
var three = 'three';

Two:

var one   = 'one',
    two   = 'two', 
    three = 'three';

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.