diff --git a/docs/coding_standards.txt b/docs/coding_standards.txt
index 432125e3c..5c5e8d6d1 100755
--- a/docs/coding_standards.txt
+++ b/docs/coding_standards.txt
@@ -8,6 +8,13 @@ Most of iD is written with [a js module pattern](http://macwright.org/2012/06/04
that is, they do not use the `new` operator, and they use scope instead of
`this` to reference variables and functions.
+The exceptions are classes that are very heavily instantiated: Graphs and entities. These are written in a
+classical manner for [performance reasons](https://gist.github.com/3961693).
+
+In order to unify the construction interface for these two styles, classical classes use the
+[instanceof trick](http://ejohn.org/blog/simple-class-instantiation/). This allows instantiation
+of both module pattern classes and classical classes to be done without using `new`.
+
Function names
--------------
Anything that creates and calls an Action should be prefixed with do:
diff --git a/index.html b/index.html
index a2692c933..d1f168fd7 100755
--- a/index.html
+++ b/index.html
@@ -47,7 +47,7 @@
-
+
@@ -74,7 +74,7 @@
iD.Hash().map(map);
iD.UI.bind();
- var controller = iD.controller(map);
+ var controller = iD.Controller(map);
d3.selectAll('button#place').on('click', function() {
controller.go(iD.actions.AddPlace);
diff --git a/js/iD/controller/controller.js b/js/iD/controller/controller.js
index 855f6e416..e9360f020 100644
--- a/js/iD/controller/controller.js
+++ b/js/iD/controller/controller.js
@@ -1,6 +1,6 @@
// A controller holds a single action at a time and calls `.enter` and `.exit`
// to bind and unbind actions.
-iD.controller = function(map) {
+iD.Controller = function(map) {
var controller = { action: null };
controller.go = function(x) {
diff --git a/js/iD/graph/Graph.js b/js/iD/graph/Graph.js
index 77f122260..13b07703b 100644
--- a/js/iD/graph/Graph.js
+++ b/js/iD/graph/Graph.js
@@ -1,4 +1,5 @@
iD.Graph = function(entities, annotation) {
+ if (!(this instanceof iD.Graph)) return new iD.Graph(entities, annotation)
this.entities = entities || {};
this.annotation = annotation;
};
@@ -36,11 +37,11 @@ iD.Graph.prototype = {
replace: function(entity, annotation) {
var o = {};
o[entity.id] = entity;
- return new iD.Graph(pdata.object(this.entities).set(o).get(), annotation);
+ return iD.Graph(pdata.object(this.entities).set(o).get(), annotation);
},
remove: function(entity, annotation) {
- return new iD.Graph(pdata.object(this.entities).remove(entity.id).get(), annotation);
+ return iD.Graph(pdata.object(this.entities).remove(entity.id).get(), annotation);
},
// get all objects that intersect an extent.
diff --git a/js/iD/graph/History.js b/js/iD/graph/History.js
index 3c2c2f61d..6ec3581a2 100644
--- a/js/iD/graph/History.js
+++ b/js/iD/graph/History.js
@@ -1,5 +1,6 @@
iD.History = function() {
- this.stack = [new iD.Graph()];
+ if (!(this instanceof iD.History)) return new iD.History();
+ this.stack = [iD.Graph()];
this.index = 0;
};
diff --git a/js/iD/renderer/Map.js b/js/iD/renderer/Map.js
index f95967dbc..f1d816041 100755
--- a/js/iD/renderer/Map.js
+++ b/js/iD/renderer/Map.js
@@ -22,8 +22,8 @@ iD.Map = function(elem) {
width, height,
dispatch = d3.dispatch('move', 'update'),
// data
- history = new iD.History(),
- connection = new iD.Connection(history.graph()),
+ history = iD.History(),
+ connection = iD.Connection(history.graph()),
inspector = iD.Inspector(history),
parent = d3.select(elem),
selection = [],