I want to write a small game using JavaScript and <canvas> but first I want to nail the "correct" or at least common approach to working with Objects.
One topic I am having trouble understanding in particular is how I could implement overriding of method.
When I create an Object, I may have this:
function MyObject()
{
var base = {};
base.i = 0;
base.update = function()
{
base.i ++;
}
return base;
}
Then when I create another Object that should start with the same members, I use this:
function AnotherObject()
{
var base = new MyObject();
base.j = 0;
return base;
}
I want to add more content to AnotherObject.update() while still running the logic I have in MyObject.update(), but when I do this within AnotherObject():
base.update = function()
{
j ++;
}
Then I of course lose the logic I added in MyObject.update().
How can I write AnotherObject.update() so that it also calls the original update() method defined by MyObject?
First, I'd suggest you read this excellent excellent MDN article. It will enlighten you.
You can achieve subclassing this way:
function MyObject() {
this.i = 0;
}
MyObject.prototype.update = function() {
this.i++;
}
function AnotherObject() {
MyObject.call(this);
this.j = 0;
}
AnotherObject.prototype = new MyObject;
AnotherObject.prototype.constructor = AnotherObject;
AnotherObject.prototype.update = function() {
MyObject.prototype.update.call(this);
this.j++;
}
obj = new AnotherObject();
console.log(obj.i); //0
console.log(obj.j); //0
obj.update();
console.log(obj.i); //1
console.log(obj.j); //1
console.log(obj instanceof MyObject) //true
console.log(obj instanceof AnotherObject) //true
+1 for zzzzBov's comment. You're using base when you should be using prototype. Not within the constructor function, but rather after the constructor function to further refine the class definition.
function MyObject() {
this.value = 5;
}
MyObject.prototype.update = function() {
this.value++;
}
Var newObject = new MyObject();
newObject.update =function() {
value--;
}
As others have suggested you should follow prototype based inheritance. That is the right way to do it.
But as a solution to what you have done so far you can do as shown below
function MyObject() {
var base = {};
base.i = 0;
base.update = function () {
this.i++;
}
base.show = function () {
console.log("i is " + this.i);
}
return base;
}
function AnotherObject() {
var base = new MyObject();
base.j = 0;
var update = base.update; // proxy variable that refers to original `update`
base.update = function () {
update.call(this); // invoke original `update`
this.j++;
}
var show = base.show; // proxy variable that refers to original `show`
base.show = function () {
show.call(this); // invoke original `show`
console.log("j is " + this.j);
}
return base;
}
var t = AnotherObject();
t.update();
t.show();
Related
I want to create a method which automatically implemented when create an instance of an object, exactly like concept of class constructor.
function myString(string) {
// Storing the length of the string.
this.length = 0;
// A private constructor which automatically implemented
var __construct = function() {
this.getLength();
}();
// Calculates the length of a string
this.getLength = function() {
for (var count in string) {
this.length++;
}
};
}
// Implementation
var newStr = new myString("Hello");
document.write(newStr.length);
I have the following error message when implement the previous code:
TypeError: this.getLength is not a function.
UPDATE:
The problem was in this scope.
The following is constructor method after updade:
var __construct = function(that) {
that.getLength();
}(this);
Bergi's answer in this thread is far more relevant: How to define private constructors in javascript?
Though a bit crude you can create a method called init and then call that method at the bottom of your function so when you instantiate a new object that code shall be run.
function myString(string) {
//Initalization function
this.init = function() {
this.calcLength();
}
// Storing the length of the string.
this.length = 0;
this.getLength = function() {
return this.length;
}
// Calculates the length of a string
this.calcLength = function() {
for (var count in string) {
this.length++;
}
};
this.init();
}
// Implementation
var newStr = new myString("Hello");
var element = document.getElementById('example');
element.innerText = newStr.getLength();
Edit: I'm aware there are better ways to achieve this, but this gets the job done.
Edit 2: Fiddle https://jsfiddle.net/ntygbfb6/3/
I have a method in a base class that I want to keep in a subclass, but just add to it. I've found lots of stuff on augmenting classes and objects with properties and methods, but I can't find, or don't understand, how to just augment the method. The worst case scenario is that I would have to paste the entire method of the parent class into the subclass, but that seems like duplicate code... please help
function someObject (){
this.someProperty = 1;
this.incrementProperty = function incrementProperty(){
this.propertyOfSomeObject += 1;
}
}
function newObject (){
someObject.call(this);
this.incrementProperty = function incrementProperty(){
//do everything the super class has for this property already
return this.someProperty;
}
}
var incrementer = new newObject;
alert (incrementer.incrementProperty()); //I want output to be 2
// parent object
function someObject () {
this.someProperty = 1;
}
// add incrementProperty to the prototype so you're not creating a new function
// every time you instantiate the object
someObject.prototype.incrementProperty = function() {
this.someProperty += 1;
return this.someProperty;
}
// child object
function newObject () {
// we could do useful work here
}
// setup new object as a child class of someObject
newObject.prototype = new someObject();
// this allows us to use "parent" to call someObject's functions
newObject.prototype.parent = someObject.prototype;
// make sure the constructor points to the right place (not someObject)
newObject.constructor = newObject;
newObject.prototype.incrementProperty = function() {
// do everything the super class has for this property already
this.parent.incrementProperty.call(this);
return this.someProperty;
}
var incrementer = new newObject();
alert (incrementer.incrementProperty()); // I want output to be 2
See: http://jsfiddle.net/J7RhA/
this should do, you have to use prototype to have a real concept of oo with javascript
function someObject (){
this.someProperty = 1;
this.propertyOfSomeObject = 0;
this.incrementProperty = function incrementProperty(){
this.propertyOfSomeObject += 1;
return this.propertyOfSomeObject;
}
}
function newObject (){
someObject.call(this);
this.incrementProperty = function incrementProperty(){
this.__super__.incrementProperty.apply(this);
return this.propertyOfSomeObject + 1;
}
}
newObject.prototype = new someObject()
newObject.prototype.__super__ = newObject.prototype
var incrementer = new newObject();
alert(incrementer.incrementProperty()); //I want output to be 2
experiment removing incrementProperty from newObject and it will return 1
I usually use the augment library to write classes in JavaScript. This is how I would rewrite your code using augment:
var Foo = Object.augment(function () {
this.constructor = function () {
this.someProperty = 1;
};
this.incrementProperty = function () {
this.someProperty++;
};
});
var Bar = Foo.augment(function (base) {
this.constructor = function () {
base.constructor.call(this);
};
this.incrementProperty = function () {
base.incrementProperty.call(this);
return this.someProperty;
};
});
As you can see since Bar extends Foo it gets Foo.prototype as a parameter (which we call base). This allows you to easily call the base class constructor and incrementProperty functions. It also shows that the constructor itself is just another method defined on the prototype.
var bar = new Bar;
alert(bar.incrementProperty());
The output will be 2 as expected. See the demo for yourself: http://jsfiddle.net/47gmQ/
From this answer:
Overriding functions
Sometimes children need to extend parent functions.
You want the 'child' (=RussionMini) to do something extra. When RussionMini can call the Hamster code to do something and then do something extra you don't need to copy and paste Hamster code to RussionMini.
In the following example we assume that a Hamster can run 3km an hour but a Russion mini can only run half as fast. We can hard code 3/2 in RussionMini but if this value were to change we have multiple places in code where it needs changing. Here is how we use Hamster.prototype to get the parent (Hamster) speed.
// from goog.inherits in closure library
var inherits = function(childCtor, parentCtor) {
function tempCtor() {};
tempCtor.prototype = parentCtor.prototype;
childCtor.prototype = new tempCtor();
childCtor.prototype.constructor = childCtor;
};
var Hamster = function(name){
if(name===undefined){
throw new Error("Name cannot be undefined");
}
this.name=name;
}
Hamster.prototype.getSpeed=function(){
return 3;
}
Hamster.prototype.run=function(){
//Russionmini does not need to implement this function as
//it will do exactly the same as it does for Hamster
//But Russionmini does need to implement getSpeed as it
//won't return the same as Hamster (see later in the code)
return "I am running at " +
this.getSpeed() + "km an hour.";
}
var RussionMini=function(name){
Hamster.apply(this,arguments);
}
//call this before setting RussionMini prototypes
inherits(RussionMini,Hamster);
RussionMini.prototype.getSpeed=function(){
return Hamster.prototype
.getSpeed.call(this)/2;
}
var betty=new RussionMini("Betty");
console.log(betty.run());//=I am running at 1.5km an hour.
I have been reading JavaScript Patterns book by Stoyan Stefanov and one of the patterns to enforcing the new operator for constructor functions goes like this
function Waffle() {
if (!(this instanceof Waffle)) {
return new Waffle();
}
this.tastes = "yummy";
}
Waffle.prototype.wantAnother = true;
when writing this way you can invoke Waffle either one of these ways
var first = new Waffle(),
second = Waffle();
I think this is a helpful feature not sure if it's implemented in future versions of ecma/javascript
I came up with something on my own that I thought could just copy and paste each time when creating a constructor function
something like this
function checkInstance (name) {
if (name.constructor.name === undefined) {
return "construct it"
} else {
return false;
}
}
function Waffle() {
var _self = checkInstance.call(this, this);
if (_self === "construct it") {
return new Waffle()
}
this.tastes = "yummy"
}
var waffle = Waffle()
waffle
Therefore I can invoke Waffle either way new Waffle or Waffle() and still have it return an object
My problem that I'm having is here
if (_self === "construct it") {
return new Waffle()
}
Is there anyway I can refer to new Waffle() without referring to the actual name of the constructor function meaning so I could copy and paste this each time and not have to change anything. Meaning I could I save Waffle() as a variable and do something like
return new var
I wish I could use this.name but that doesn't work either until it is invoked.
I have a feeling I can't but wanted to at least ask some of the people here on stack overflow if it was a possibility
Again your comments and feedback is appreciated
I have a better solution. This is what you're currently doing:
function Waffle() {
if (!(this instanceof Waffle))
return new Waffle;
this.tastes = "yummy";
}
Waffle.prototype.wantAnother = true;
This pattern isn't really nice because you're mixing the code to construct a new object with the code to check if the new keyword is being used.
I've mentioned before that you shouldn't use the new keyword in JavaScript as it breaks functional features. Instead let's create another function which does the same thing:
Function.prototype.new = (function () {
return function () {
functor.prototype = this.prototype;
return new functor(this, arguments);
};
function functor(constructor, args) {
return constructor.apply(this, args);
}
}());
This function allows you to create an instance of a function as follows:
var waffle = Waffle.new();
However we don't want to use new at all. So to do away with it we'll create a function which wraps a constructor as follows:
function constructible(constructor) {
function functor() { return Function.new.apply(constructor, arguments); }
functor.prototype = constructor.prototype;
return functor;
}
Now we can define the Waffle function as follows:
var Waffle = constructible(function () {
this.tastes = "yummy";
});
Waffle.prototype.wantAnother = true;
Now you can create objects with or without using new:
var first = new Waffle;
var second = Waffle();
Note: The constructible function is pretty slow. Use the following version of constructible instead - it's a little faster:
function constructible(constructor) {
constructor = Function.bind.bind(constructor, null);
function functor() { return new (constructor.apply(null, arguments)); }
functor.prototype = constructor.prototype;
return functor;
}
Personally I wouldn't use either of these two methods. I would just remember to write new, or (more likely) I would restructure my code as follows:
var waffle = {
create: function () {
var waffle = Object.create(this);
waffle.tastes = "yummy";
return waffle;
},
wantAnother: true
};
var first = waffle.create();
var second = waffle.create();
If you want to know more about this pattern then read the following answer: https://stackoverflow.com/a/17008403/783743
You could use something like this:
var Waffle = (function() {
function Waffle() {
this.tastes = "yummy"
}
return exportCtor( Waffle );
})();
var waffle = Waffle();
alert(waffle.tastes);
console.log(Waffle);
/*
function ConstructorProxy() {
"use strict";
return new Constructor();
}
*/
http://jsfiddle.net/ywQJF/
It handles variable arguments too
arguments.callee, which refers to the current function, is the most simple solution. It's is deprecated, though, so use it at your own risk.
function Waffle() {
if (!(this instanceof arguments.callee))
return new arguments.callee();
this.tastes = 'yummy';
}
It's a hard problem also because you probably want to preserve the arguments you're passing, as Vinothbabu mentioned. But if you real intention is enforcing new, you could simply throw an error, which is a simple two lines of code:
if (!(this instanceof Waffle))
throw new Error('Constructor called without new');
You could even wrap it in a function:
function cons(C) {
var c = function () {
if (!(this instanceof c))
throw new Error('Constructor called without new');
C.apply(this, arguments);
};
c.prototype = C.prototype;
return c;
}
var Waffle = cons(function () {
this.tastes = 'yummy';
});
Waffle.prototype.wantAnother = function () {
return true;
};
new Waffle(); // { tastes: 'yummy', 'wantAnother': true }
Waffle(); // throws error
Now Waffle must be called with new -- otherwise, it throws an error.
The best approach, in my opinion, is not to enable yourself to invoke things incorrectly:
function Waffle() {
if (!(this instanceof Waffle)) {
throw "Waffles need to be fresh or they're gross. Use 'new'.";
}
}
But, if you simply must enable yourself to write inconsistent code, make initialization a separate step.
function Waffle(options) {
var o = options || {};
if (this instanceof Waffle) {
this.init = function() {
/* this is really your constructor */
console.log("initializing ... ");
}
if (!o.__do_not_initialize) {
this.init(arguments);
}
} else {
var rv = new Waffle( { __do_not_initialize: true } );
rv.init(arguments);
return rv;
}
}
If you want to force consistency the other way -- never using the new keyword, create a builder function:
function BuildWaffle(options) {
var o = options || {};
if (this instanceof WaffleBuilder) {
throw "BuildWaffle cannot be instantiated.";
}
var Waffle = function Waffle() { /* whatever */ }
Waffle.prototype.doStuff = function() { /* whatever else */ }
var rv = new Waffle(options);
return rv;
}
There is simpler way how to enforce creation of new object even without new:
function Waffle() {
return {tastes:"yummy"};
}
var a = Waffle();
var b = new Waffle();
alert(a.tastes); // yummy
alert(b.tastes); // yummy
Explanation
Using new with function, there are two possibilities:
the function returns object: the object is the result of the new function() expression
the function doesn't return object: the function itself with new context is returned
See the ECMA script documentation
Workaround: prototype and arguments
function Waffle(taste,how) {
return {
tastes: taste+" "+how,
__proto__: Waffle.prototype
}
}
Waffle.prototype.wantmore = "yes";
var a = Waffle("yummy","much");
var b = new Waffle("gummy","little");
console.log(a.tastes,b.tastes); // yummy much, gummy little
console.log(a.wantmore,b.wantmore); // yes, yes
This deserves a fiddle.
Note: constructor.name (which you used in your pattern) is not standard
Note 2: __proto__ is also not standard, but is supported by modern browsers and will be standardized in ES6.
if (!(this instanceof Waffle)) {
return new Waffle();
}
This has two problems...
one that it won 't work in an anonymous function which has no name
it loses all arguments sent to the constructor.
Using a more generic approach might look something more like this:
if (!instanceExists(this, arguments)) {
return requireInstance(this, arguments);
}
This approach ensures that the constructor is called with new, without having to state the function'
s name, andadds all arguments sent to the constuctor so they aren 't lost during the process.
Here 's the full code for the above:
Function.prototype.callNew = function (args) {
var a = [];
for (var i = 0; i < args.length; i++) a.push("a[" + i + "]");
var fn = new Function("var a=arguments;return new this(" + a.join(",") + ");");
return fn.apply(this, args);
}
function instanceExists(t, args) {
if (t instanceof args.callee) {
return true;
} else {
return false;
}
}
function requireInstance(t, args) {
var fn = args.callee;
if (!instanceExists(t, args)) {
return fn.callNew(args);
}
}
function Waffle(one, two, three) {
if (!instanceExists(this, arguments)) {
return requireInstance(this, arguments);
}
this.one = one;
this.two = two;
this.three = three;
}
Waffle.prototype.serve = function () {
var out = [];
for (var j in this) {
if (!this.hasOwnProperty(j)) continue;
out.push(j + ': ' + this[j]);
}
return ' {
' + out.join(",\n") + '
}
';
}
A fiddle for you to play with.
http://jsfiddle.net/RkPpH/
var waffle = Waffle(1, 2, 3);
alert(waffle.serve());
I didn't get a sense of whether this was client or server-side, but a pattern I use sometimes goes as follows. I use this in Node but have attempted to make it a possible client-side solution as well - the Node-specific stuff is commented out but there for reference depending on your environment.
First, I create something to be used along the lines of a traditional OO base or super class like so:
//// Node:
//module.exports.Base = Base;
function Base(opts) {
var self = this;
if (!(self instanceof Base)) return new Base(opts);
self.opts = opts || {};
}
Upon which you can define your methods, in usual the fashion. You can even manually throw if the method should be provided by subclasses implementing something like abstract:
// commonMethod is available to subclasses:
Base.prototype.commonMethod = function () {
var self = this;
//access self.opts to get the constructor arguments.
//makes self always point to the right object.
}
// Provide abstractMethod, but subclass is responsible for implementation:
Base.prototype.abstractMethod = function () {
//or throw an error if this should be implemented by subclasses:
throw new Error('implement me');
}
Now you can do this:
//// If using Node:
//var inherits = require('util').inherits;
//var Parent = require('./Base').Base;
function Sub (opts) {
var self = this;
//// If using node and you want super_ to be called prior to creating a new Sub:
//if(Sub.super_) Sub.super_.call(this, opts);
// Always do this:
if (!(self instanceof Sub)) return new Sub(opts);
//// If using node and you are ok with super_ called after creating new Sub:
//if(Sub.super_) Sub.super_.call(this, opts);
//// otherwise:
parent(opts);
}
//// If using Node:
//inherits(Sub, Base);
//// Otherwise:
Sub.prototype.constructor = Base;
Sub.prototype.parent = Base.prototype;
//and provide the implementation of abstractMethod:
Sub.prototype.abstractMethod() {
//...
}
And to formally answer the specific question, all of the
if (!(self instanceof Sub)) return new Sub(opts);
is where you get the guaranteed new situation.
First of all, I took the animals example from the coffeescript site.
I want to simulate next things in javascript:
Classes
Public methods only
Private methods and variables only
Inheritance
Call methods from the super class
I think this way to create this is ok, but when I try to get the move method from the parent class, always it returns to itself. What I'm doing wrong?
BTW. Which are the best practices to achieve my goal? Is right what I'm doing?
var Animal = (function() {
function Animal() {}
var _private = {};
var _public = {
move: function() {
console.log('Can move');
}
};
Animal.prototype = _public;
Animal.prototype.constructor = Animal;
return Animal;
})();
var Snake = (function(_super) {
function Snake() {}
var _private = {};
var _public = {
move: function() {
console.log(Snake._super_.move);
console.log('Slithering');
}
};
Snake.prototype = _super.prototype;
Snake._super_ = _super.prototype;
for(var method in _public) {
if(Object.prototype.toString.call(_public[method]) === '[object Function]') {
Snake.prototype[method] = _public[method];
}
}
return Snake;
})(Animal);
var s = new Snake;
s.move();
This is very well written code in my opinion, with just one small mistake.
I think you got your pointers a little crossed, try this:
<script>
var Animal = (function () {
function Animal() { }
var _private = {};
var _public = {
move: function () {
console.log('Can move');
//this just returns a string to show which method was called
//inside of the child's move function's console.log
return "super move called";
}
};
Animal.prototype = _public;
Animal.prototype.constructor = Animal;
return Animal;
})();
var Snake = (function (_super) {
function Snake() { }
var _private = {};
var _public = {
move: function () {
console.log(Snake._super_.move());//Now we can call super's move
console.log('Slithering');
}
};
//This created the circular reference where Snake._super_ was pointing to
//Snake.prototype which was causing the error
//Snake.prototype = _super.prototype;
Snake._super_ = _super.prototype;
for (var method in _public) {
if (Object.prototype.toString.call(_public[method]) === '[object Function]') {
Snake.prototype[method] = _public[method];
}
}
return Snake;
})(Animal);
var s = new Snake;
s.move();//now this outputs "Can move", "super move called", "Slithering"
</script>
If you are asking for best practices, I'd say take any of ready to go solutions on the web. I prefer this one: http://canjs.us/#can_construct.
A few notices about your approach:
It's not reusable. You have to write the same code for every single class. At least you should extract for-loop to make this piece of code reusable.
You need to check _public.hasOwnProperty(method) to make your code more robust.
toString and valueOf methods require special handling since they are non-enumerable in IE<9.
Snake.prototype = _super.prototype; is a complete disaster. Since your super class will have all methods of child.
var F = function(){};
F.prototype = _super.prototype;
Snake.prototype = new F();
Snake.prototype.constructor = Snake;
I was experimenting with some examples and came across a problem that if we want to add a function to a prototype it will not be able to access the private members of the constructor. I came across this solution. This seems to be a nice hack.
I tried out some other ways and I got the following:
var Restaurant = function()
{
var myPrivateVar;
var private_stuff = function() // Only visible inside Restaurant()
{
return "I can set this here!";
}
Restaurant.prototype.use_restroom = function() // use_restroom is visible to all
{
private_stuff();
}
Restaurant.prototype.buy_food = function() // buy_food is visible to all
{
return private_stuff();
}
}
var restaurant = new Restaurant();
restaurant.buy_food(); // this would work
restaurant.private_stuff(); // this won't
The solution seems weird because we are adding to the prototype within the constructor function. (I haven't seen much of this). It works on firefox 5 and chrome at least. Is there something wrong with it?
What you're doing is redefining those methods on the prototype every time you make a new restaurant object. The more sane way to do that would be to define them on this, which is the new object being constructed in a constructor:
var Restaurant = function()
{
var myPrivateVar;
var private_stuff = function() // Only visible inside Restaurant()
{
return "I can set this here!";
}
this.use_restroom = function() // use_restroom is visible to all
{
private_stuff();
}
this.buy_food = function() // buy_food is visible to all
{
return private_stuff();
}
}
You could just do it like this though, and not use new:
var RestaurantMaker = function () {
var myPrivateVar;
var private_stuff = function() {
return "I can set this here!";
}
return {
use_restroom: function () {
private_stuff();
},
buy_food: function () {
return private_stuff();
}
};
}
and then just do:
var restaurant = RestaurantMaker();
This is called the revealing module pattern. The downside is that each new object gets a copy of all the functions, which also happens if you add methods to this in your constructor.
A very small alternative version of the revealing module pattern (which I think reads a bit better) looks like this:
var RestaurantMaker = function () {
var myPrivateVar;
function private_stuff() {
return "I can set this here!";
}
function use_restroom() {
private_stuff();
}
function buy_food() {
return private_stuff();
}
return {
use_restroom: use_restroom,
buy_food: buy_food
};
}
Then, if you want to change whether a function is private or not, it's just a matter of adding or removing it from the returned object.
I didn't actually test this, but I think all the objects would access to the last instantiated object's private properties.
On each instantiation you're binding the prototype methods (shared across all instances) to the private variables of the object being instantiated :)
Honestly, it doesn't make a lot of sense to me. Sure, you can have calls to your private functions this way, but it doesn't solve the initial problem - that is, you still need to add methods inside the constructor.
If you want to add methods to the class outside the constructor, you can use closures to keep constructors clean:
// Creating a closure inside a self-calling function
var Restaurant = (function() {
// Only visible inside this closure
var myPrivateVar;
var private_stuff = function() {
return "I can set this here!";
}
var Restaurant = function() {};
// use_restroom is visible to all
Restaurant.prototype.use_restroom = function() {
private_stuff();
};
// buy_food is visible to all
Restaurant.prototype.buy_food = function() {
return private_stuff();
};
// We give back the Restaurant-constructor to the people
return Restaurant;
})();
var restaurant = new Restaurant();
restaurant.buy_food(); // this would work
restaurant.private_stuff(); // this won't
We take a different approach. We do use closures sometimes, but only when you need to manage state at the class level. We use namespaces to manage scope. For a simple class with prototype methods, we just do this:
/**
* #namespace
*/
var chain = {};
(function () {
/**
* The constructor is used to manage private data
* #constructor
*/
chain.Restaurant = function () {
// Only visible inside this constructor
var inventory = { };
/**
* add an item with a count to the inventory
* This is a privileged function.
* #param {String} item The identifier for the item you are adding
* #param {String} count The count you are adding for the item.
*/
this.addInventory = function (item, count) {
if (count < 0) {
// throw an error
}
var current = this.getInventory(item);
inventory[item] = current + count;
}
// privileged function
this.getInventory = function (item) {
if (inventory.hasOwnProperty(item)) {
return inventory[item];
}
return 0;
}
// privileged function
this.removeInventory = function (item, count) {
throwIfNegative(count);
if (this.getInventory(item) < count) {
throw new Error("Inventory Unavailable");
}
inventory[item] -= count;
}
// private function, only visible to the privileged functions
function throwIfNegative (value) {
if (value < 0) {
throw new Error("Negative Inventory Is Not Valid");
}
}
}
// member/prototype method
chain.Restaurant.prototype.sellInventory = function (item, count) {
var availabe = this.getInventory(item);
var sellCount = Math.min(available, count, 0);
if (sellCount > 0) {
// do this conditionally if there are implications to invoking the functions
this.removeInventory(sellCount);
sellItem(item, sellCount);
}
return sellCount;
}
// member/prototype method
chain.Restaurant.prototype.hasInventory = function (item, count) {
return this.getInventory(item) >= count;
}
// namespace method
chain.soldQuantity = function (item) {
if (!itemsSold.hasOwnProperty(item)) {
return 0;
}
return itemsSold[item];
}
// functions defined in this closure can see this
var itemsSold = { };
// all functions defined in this closure can call this
function sellItem (item, quantity) {
if (!itemsSold.hasOwnProperty(item)) {
itemsSold[item] = 0;
}
itemsSold[item] += quantity;
}
})();