Programs are meant to be read by humans, only incidentally by computers to execute
Donald Knuth
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.
— Kyle Richter (@kylerichter) December 15, 2010
If there is a feature of the language that is sometimes problematic, and if it can be replaced with another feature that is more reliable, then always use the more reliable feature.
Douglas Crockford
// any number that isn't zero evaluates to TRUE
var a = [1, 2, 3];
while (a.length) {
// do something with array
}
// any string that isn't empty evaluates to TRUE
var s = "This is interesting";
if (s) {
// while s.length is a postive number,
// we can just evaluate the string.
}
// any object reference that isn't null or undefined
// evaluates to TRUE
var o = {};
if (o) {
// 'o' exists, let's do something with it
}
// an example ajax success callback
// receiving (parsed) JSON data
function success(data) {
// check if data was returned as array
if (data && data.length) {
// do something with the array
} else if (data) {
// only one object
}
}
// "zero" (0) evalues to FALSE
var elements = $('#Container > div');
if (!elements.length) {
// There are no elements in this jQuery object
}
// An empty string ('') evaluates to FALSE
var s = '';
if (!s) {
// Do something with the empty string
}
// "undefined" evaluates to FALSE
var data;
if (!data) {
// data is not defined ('undefined' by default)
}
// "null" evaluates to FALSE
function Widget() {
this.element = null;
}
var w = new Widget();
if (!w.element) {
// element is null
}
// Because of "false", we have "coalesce"
(function() {
// CSN is the root namespace
// If it hasn't already been defined, do so
// Thanks to the short circuit "or",
// the left side will evalute to FALSE
// and assign an empty object to the
// global "CSN" and the local variable.
var CSN = window.CSN || (window.CSN = {});
}());
(function($, CSN) {
// define hidden objects and variables here
// define functions, classes here that are part of namespaces
// define jQuery plugins
}(jQuery, (window.CSN || (window.CSN = {}))));
(function(CSN){
// "CSN" is the root namespace
// Check if the "Utils" namespace has been defined
// and then use an alias variable to ease typing
var utils = CSN.Utils || (CSN.Utils = {});
// Add public functions to CSN.Utils
utils.format = function(s) {
// defines CSN.Utils.format()
};
}((window.CSN || (window.CSN = {}))));
// You need to record the index of each element
var element, inputs = document.getElementById('Module').getElementsByTagName('input');
for (var i, j = inputs.length; i < j; i++) {
element = inputs.eq(i);
// Retain the value of "i" for each iteration
// By passing the value into this IIFE
(function(i) {
element.on('focus', function() {
// do something with "i"
$(this).data('index', i);
});
})(i);
}
// You need to record the index of each element
// Even better
$('#Module input').each(function(i, element){
// Each index is recorded
$(element).data('index', i);
});
function Widget(element) {
this.element = element;
}
Widget.prototype.change = function() {};
Widget.prototype.init = function() {
this.element.on('click', function() {
// In here, "this" refers to the element
});
}
function Widget(element) {
this.element = element;
}
Widget.prototype.change = function() {};
Widget.prototype.init = function() {
var that = this;
this.element.on('click', function() {
// In here, "this" refers to the element
// But we can use "that"
// to refer to the containing object
that.change();
});
}
'use strict';
// Using Function.bind()
function Widget(element) {
this.element = element;
}
Widget.prototype.change = function() {};
Widget.prototype.init = function() {
var that = this;
this.element.on('click', function(ev) {
// In here "this" refers to
// the containing object
this.change();
}.bind(this));
}
// Function currying
JsonpService.postAjax = function (aspect, canPipe, itemCountKey) {
return function (data, error, msg) {
var newCount;
if (!error) {
newCount = parseInt(data[itemCountKey], 10);
if (!isNaN(newCount)) {
this.itemCount = newCount;
}
if (canPipe) {
data = this.pipe("out", data);
}
this.notify(aspect, data);
if (this.itemCount >= this.maximum) {
this.notify("full", this.itemCount);
}
} else {
this.errorHandler(error, msg);
}
};
};
JsonpService.prototype.create = function (data) {
var handler = JsonpService.postAjax("create", true, "NewCount");
// wrap in jQuery.proxy to improve lexical scope
// and pass the handler to jQuery.ajax
};
(function($) {
'use strict';
// "ToolboxWidget" class is hidden from outside world
function ToolboxWidget(element) {
this.element = element;
// Define other properties
}
ToolboxWidget.prototype.init = function() {
// Initialize state
// Invoke other setup methods
};
$.fn.toolbox = function(options) {
options = $.extend({}, $.fn.toolbox.defaults, options);
this.each(function() {
// The ToolboxWidget handles the state
// of the object. We're reducing the
// number of DOM interactions to
// improve performance.
var w = new ToolboxWidget($(this));
w.init();
// do more with widget
w.data('widget', w);
});
return this;
};
$.fn.toolbox.defaults = {};
}(jQuery));
<body>
<!-- generated HTML here -->
<!-- scripts at bottom of page for performance -->
<script src="./scripts/toolbox-widget.js"></script>
<!-- define entry point for Toolbox Widget, with configuration -->
<script>
(function($){
$("#Toolbox").toolbox({searchUrl:"/results/{0}"});
}(jQuery));
</script>
</body>
<body>
<!-- generated HTML here -->
<!-- scripts at bottom of page for performance -->
<script src="./scripts/app.js"></script>
<!-- set up, with configuration -->
<script>
(function($){
CSN.App.init({startPage:2});
}(jQuery));
</script>
</body>
function someMethod() {
return
{
name: "Peter"
}
}
function someMethod() {
return {
name: "Peter"
};
}
if (a > 10)
doThis();
else
doThat();
if (a > 10)
doThis();
else
doThat();
doSomethingElse();
if (a > 10) {
doThis();
doSomethingElse();
} else {
doThat();
}
// typeof "ABC" == "string"
// typeof 2134 == "number"
// typeof {} == "object"
// typeof function() {} == "function"
// typeof null == "object"
// typeof [] == "object"
// typeof undefined == "undefined"
var a = "123";
if (a == 123) {
// TRUE
// a is "coerced" into a number
}
var b;
if (b == null) {
// TRUE
// "undefined" is coerced into being "null"
}
var a = "123";
if (a === 123) {
// a HAS to be a number for this to be TRUE
}
var b;
if (b === null) {
// b MUST have null assigned to it to be TRUE
}
// even better:
if (!b) {
// use FALSY rule
}
(function() {
'use strict';
// OK, define module
// Any variable not defined will throw an error
}());
(function() {
'use strict';
var a = [1, 2, 3];
a.forEach(function(item) {
// do something on each array element
});
}());
(function() {
'use strict';
var person = {
firstName: 'Peter',
lastName: 'Berry',
age: 41,
lives: 'Brunswick'
};
// Object.keys returns an array of properties
var properties = Object.keys(person);
// We can then use forEach to enumerate
// This code will output the value of each property
properties.forEach(function(p){
console.log(person[p]);
});
}());
jQuery("body").on('click', function() {
a = a + 1
if (a == 1) alert('Hello World);
})
jQuery("body").on('click', function() {
a = a + 1
if (a == 1) alert('Hello World);
})
{ "name": "Peter","description":"has written some dodge code in the past", "flagged":true, "age":41}
{ "name": "Peter","description":"has written some dodge code in the past", "flagged":true, "age":41}
Code in a manner that another developer, who is not familiar with JavaScript, can comprehend the intent of the code.
Handling events and passing to nested functions is messy - "callback hell"
Promises has a fluent API
// Nested callbacks
http.get(url.parse("http://example.org/"), function (res) {
console.log(res.statusCode); // maybe 302
http.get(url.parse(res.headers["location"]), function (res) {
console.log(res.statusCode); // maybe 200
});
});
// Promises
httpGet(url.parse("http://example.org/")).then(function (res) {
console.log(res.statusCode); // maybe 302
return httpGet(url.parse(res.headers["location"]));
}).then(function (res) {
console.log(res.statusCode); // maybe 200
});
function makeDo(arg) {
if (arg.isValid) {
let a = arg.value;
// do something with a
// "a" is in block scope
}
}
Hosted by: Alastair Burrowes