Skip to content

Instantly share code, notes, and snippets.

@jesstelford
Last active August 29, 2015 13:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jesstelford/9383044 to your computer and use it in GitHub Desktop.
Save jesstelford/9383044 to your computer and use it in GitHub Desktop.
Minimal node.js express example showcasing hoisting, type coercion, module patterns, closures, strict mode, and how to avoid nasty `undefined` issues.
# The same as `index.js`, but in Coffeescript. Try it out here: http://michaelficarra.github.io/CoffeeScriptRedux/#try:
express = require 'express'
class Foo
'use strict'
defaultQuery = {}
query: undefined
toString: ->
if @query?
"query = #{JSON.stringify @query}"
else
"query = #{JSON.stringify defaultQuery}"
constructor: (q) ->
@query = q
app = express()
app.get '/foo', (req, resp, err) ->
f = new Foo req.query
resp.send 200, "#{f}"
app.listen 3000
console.log "Listening to http://localhost:3000"
# Visit http://localhost:3000/foo?bar=zip
# You should see outputted:
# {bar: "zip"}
// Use npm to include the 'express' module
var express = require('express');
// Creating a new module that we'll call 'Foo'
// The 'undef' parameter is not populated since where it is called (on line
// 47), nothing was passed. By default, this means the value of `undef` will be
// `undefined`. This is a protection against a malicious application changing
// the value of the `undefined` variable. NOTE: This isn't necessary since we're
// using strict mode which protects against this for us
var Foo = function(undef) {
// Force 'strict' mode to better handle errors, etc
'use strict';
// a variable we will use later in a closure
var defaultQuery = {}
// This is a variable which will exist on any instance of this module
// Default it to undefined
Module.prototype.query = undef;
// Overriding the default `.toString` method of `Function` (since `Module` is
// a `Function`)
Module.prototype.toString = function() {
// Using loose equality, checking for `null` will also check for `undefined`
// ie; null == undefined is true, but null === undefined is false
if (this.query != null) {
// `this` refers to the instance of the module
return "query = " + JSON.stringify(this.query);
} else {
// using a variable that was closed over into this scope (since this
// .toString() method is a closure)
return "query = " + JSON.stringify(defaultQuery);
}
};
// Executed when a new instance of this module is created with `new Foo()`
// This definition is 'hoisted' to the top of the block scope, which is what
// allowed us to do `Module.prototype.query = {}` above without an 'undefined
// reference' error.
function Module(q) {
// `this` refers to the instance of the module
this.query = q;
}
// This gets assigned to the variable `Foo` above
return Module;
}()
// Sets up a new HTTP server
app = express();
// Add a single GET route of 'http://whatever.tld/foo'
// See: http://expressjs.com/3x/api.html#app.VERB
app.get('/foo', function(req, resp, err) {
// Create a new instance of 'Foo', and pass it an object, which is the query
// parameters of the GET request
var f = new Foo();
// Send a response from the server
// Note the `'' + f` - this uses type coercion to treat `f` as a string.
// Since `f` isn't a string (it's an Object), it tries to get a string
// representation of it by calling `.toString()` automagically. ie; It calls
// the `.toString()` we defined in the `Foo` module above.
resp.send(200, '' + f);
});
// Start the server running, listening on port 3000
app.listen(3000);
// Just some stdout output to show we're ready to accept requests
console.log("Listening to http://localhost:3000");
// Visit http://localhost:3000/foo?bar=zip
// You should see outputted:
// {bar: "zip"}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment