function log(result) { var li; if (typeof(resultsList) === "undefined") { console.log(result); } else { li = document.createElement("li"); li.textContent = result; resultsList.appendChild(li); } } log("Different ways of using a mixin to create property getter functions for model objects ..."); log("The model object properties are encapsulated and only accessible via the getter functions."); log("See mixin.js for implementation details."); // ************************************************ // // Standard getter method accessing variables in closure (no use of mixin). // function Model1(options) { var myOptions = options; this.get = function(prop) { return myOptions[prop]; }; } log("----"); log("Standard getter method accessing variables in closure (no use of mixin)."); log("m1 = new Model1({ a:1, b:3, c:3 });"); log("a = m1.get('a'));"); m1 = new Model1({ a:1, b:3, c:3 }); log("a = " + m1.get("a")); // ************************************************ // // Standard getter mixin accessing variables saved as properties in Model object // // See: section 4. Adding Caching // http://javascriptweblog.wordpress.com/2011/05/31/a-fresh-look-at-javascript-mixins/ // // var addMixin2 = (function() { function get(prop) { return this.options[prop]; } return function() { this.get = get; return this; }; })(); function Model2(options) { addMixin2.call(Model2.prototype); this.options = options; } log("----"); log("Standard getter mixin addMixin2() accessing variables saved as properties in Model object."); log("m2 = new Model2({ a:4, b:5, c:6 });"); log("a = m2.get('a'));"); m2 = new Model2({ a:4, b:5, c:6 }); log("=> " + m2.get("a")); // ************************************************ // // Getter mixin accessing closure variables with the help of function in Model object // var addMixin3 = (function() { function get(prop) { return this.getPrivate()[prop]; } return function() { this.get = get; return this; }; })(); function Model3(options) { addMixin3.call(Model3.prototype); var myOptions = options; this.getPrivate = function() { return myOptions; }; } log("----"); log("Getter mixin addMixin3() accessing closure variables with the help of function in Model object."); log("m3 = new Model3({ a:7, b:8, c:9 });"); log("a = m3.get('a'));"); m3 = new Model3({ a:7, b:8, c:9 }); log("=> " + m3.get("a")); var Model3a = function(options) { addMixin3.call(Model3a.prototype); var myOptions = options; this.getPrivate = function() { return myOptions; }; }; log("Make a second model object with different initial variables."); log("m3a = new Model3({ a:1, b:3, c:3 });"); log("a = m3a.get('a'));"); m3a = new Model3({ a:1, b:3, c:3 }); log("=> " + m3a.get("a")); // ************************************************ // // Mixin accessing it's own closure variables // // 'count' is scoped to the function mixed in to the model object // 'total' is scoped to the mixin itself // var addMixin4 = (function() { var total = 0; function counter(num) { var count = num; return function() { total++; return count++; }; } function totalCount() { return function() { return total; }; } return function(num) { this.counter = counter(num); this.totalCount = totalCount(); return this; }; })(); function Model4(num) { addMixin4.call(Model4.prototype, num); } var Model4a = function(num) { addMixin4.call(Model4a.prototype, num); }; log("----"); log("Mixin accessing it's own closure variables that keeps track of both how many "); log("times the mixin is called from each created function and also the total number"); log("times the mixin has been called from all functions that use it."); log("In this case two different Model creation functions are created, Model4()"); log("and Model4A() and each of them are extended with the same mixin: addMixin4()."); log("m4 = new Model4(23);"); log("m4a = new Model4a(17);"); m4 = new Model4(23); m4a = new Model4a(17); log("function call counter tests ..."); log("m4 function counter starting at 23 ..."); log("m4.counter(); => " + m4.counter()); log("m4.counter(); => " + m4.counter()); log("m4.counter(); => " + m4.counter()); log("m4.counter(); => " + m4.counter()); log("total count by all uses of mixin: " + m4.totalCount()); log("m4a counter starting at 17 ..."); log("m4a.counter(); => " + m4a.counter()); log("m4a.counter(); => " + m4a.counter()); log("m4a.counter(); => " + m4a.counter()); log("total count by all uses of mixin addMixin4(): " + m4.totalCount());