Adding functions to the same namespace [duplicate] - javascript

How do I create a namespace in JavaScript so that my objects and functions aren't overwritten by other same-named objects and functions? I've used the following:
if (Foo == null || typeof(Foo) != "object") { var Foo = new Object();}
Is there a more elegant or succinct way of doing this?

I use the approach found on the Enterprise jQuery site:
Here is their example showing how to declare private & public properties and functions. Everything is done as a self-executing anonymous function.
(function( skillet, $, undefined ) {
//Private Property
var isHot = true;
//Public Property
skillet.ingredient = "Bacon Strips";
//Public Method
skillet.fry = function() {
var oliveOil;
addItem( "\t\n Butter \n\t" );
addItem( oliveOil );
console.log( "Frying " + skillet.ingredient );
};
//Private Method
function addItem( item ) {
if ( item !== undefined ) {
console.log( "Adding " + $.trim(item) );
}
}
}( window.skillet = window.skillet || {}, jQuery ));
So if you want to access one of the public members you would just go skillet.fry() or skillet.ingredients.
What's really cool is that you can now extend the namespace using the exact same syntax.
//Adding new Functionality to the skillet
(function( skillet, $, undefined ) {
//Private Property
var amountOfGrease = "1 Cup";
//Public Method
skillet.toString = function() {
console.log( skillet.quantity + " " +
skillet.ingredient + " & " +
amountOfGrease + " of Grease" );
console.log( isHot ? "Hot" : "Cold" );
};
}( window.skillet = window.skillet || {}, jQuery ));
The third undefined argument
The third, undefined argument is the source of the variable of value undefined. I'm not sure if it's still relevant today, but while working with older browsers / JavaScript standards (ecmascript 5, javascript < 1.8.5 ~ firefox 4), the global-scope variable undefined is writable, so anyone could rewrite its value. The third argument (when not passed a value) creates a variable named undefined which is scoped to the namespace/function. Because no value was passed when you created the name space, it defaults to the value undefined.

I like this:
var yourNamespace = {
foo: function() {
},
bar: function() {
}
};
...
yourNamespace.foo();

Another way to do it, which I consider it to be a little bit less restrictive than the object literal form, is this:
var ns = new function() {
var internalFunction = function() {
};
this.publicFunction = function() {
};
};
The above is pretty much like the module pattern and whether you like it or not, it allows you to expose all your functions as public, while avoiding the rigid structure of an object literal.

Is there a more elegant or succinct way of doing this?
Yes. For example:
var your_namespace = your_namespace || {};
then you can have
var your_namespace = your_namespace || {};
your_namespace.Foo = {toAlert:'test'};
your_namespace.Bar = function(arg)
{
alert(arg);
};
with(your_namespace)
{
Bar(Foo.toAlert);
}

I normally build it in a closure:
var MYNS = MYNS || {};
MYNS.subns = (function() {
function privateMethod() {
// Do private stuff, or build internal.
return "Message";
}
return {
someProperty: 'prop value',
publicMethod: function() {
return privateMethod() + " stuff";
}
};
})();
My style over the years has had a subtle change since writing this, and I now find myself writing the closure like this:
var MYNS = MYNS || {};
MYNS.subns = (function() {
var internalState = "Message";
var privateMethod = function() {
// Do private stuff, or build internal.
return internalState;
};
var publicMethod = function() {
return privateMethod() + " stuff";
};
return {
someProperty: 'prop value',
publicMethod: publicMethod
};
})();
In this way I find the public API and implementation easier to understand. Think of the return statement as being a public interface to the implementation.

Because you may write different files of JavaScript and later combine or not combine them in an application, each needs to be able to recover or construct the namespace object without damaging the work of other files...
One file might intend to use the namespace namespace.namespace1:
namespace = window.namespace || {};
namespace.namespace1 = namespace.namespace1 || {};
namespace.namespace1.doSomeThing = function(){}
Another file might want to use the namespace namespace.namespace2:
namespace = window.namespace || {};
namespace.namespace2 = namespace.namespace2 || {};
namespace.namespace2.doSomeThing = function(){}
These two files can live together or apart without colliding.

Here's how Stoyan Stefanov does it in his JavaScript Patterns book which I found to be very good (it also shows how he does comments that allows for auto-generated API documentation, and how to add a method to a custom object's prototype):
/**
* My JavaScript application
*
* #module myapp
*/
/** #namespace Namespace for MYAPP classes and functions. */
var MYAPP = MYAPP || {};
/**
* A maths utility
* #namespace MYAPP
* #class math_stuff
*/
MYAPP.math_stuff = {
/**
* Sums two numbers
*
* #method sum
* #param {Number} a First number
* #param {Number} b Second number
* #return {Number} Sum of the inputs
*/
sum: function (a, b) {
return a + b;
},
/**
* Multiplies two numbers
*
* #method multi
* #param {Number} a First number
* #param {Number} b Second number
* #return {Number} The inputs multiplied
*/
multi: function (a, b) {
return a * b;
}
};
/**
* Constructs Person objects
* #class Person
* #constructor
* #namespace MYAPP
* #param {String} First name
* #param {String} Last name
*/
MYAPP.Person = function (first, last) {
/**
* First name of the Person
* #property first_name
* #type String
*/
this.first_name = first;
/**
* Last name of the Person
* #property last_name
* #type String
*/
this.last_name = last;
};
/**
* Return Person's full name
*
* #method getName
* #return {String} First name + last name
*/
MYAPP.Person.prototype.getName = function () {
return this.first_name + ' ' + this.last_name;
};

I use this approach:
var myNamespace = {}
myNamespace._construct = function()
{
var staticVariable = "This is available to all functions created here"
function MyClass()
{
// Depending on the class, we may build all the classes here
this.publicMethod = function()
{
//Do stuff
}
}
// Alternatively, we may use a prototype.
MyClass.prototype.altPublicMethod = function()
{
//Do stuff
}
function privateStuff()
{
}
function publicStuff()
{
// Code that may call other public and private functions
}
// List of things to place publically
this.publicStuff = publicStuff
this.MyClass = MyClass
}
myNamespace._construct()
// The following may or may not be in another file
myNamespace.subName = {}
myNamespace.subName._construct = function()
{
// Build namespace
}
myNamespace.subName._construct()
External code can then be:
var myClass = new myNamespace.MyClass();
var myOtherClass = new myNamepace.subName.SomeOtherClass();
myNamespace.subName.publicOtherStuff(someParameter);

This is a follow-up to user106826's link to Namespace.js. It seems the project moved to GitHub. It is now smith/namespacedotjs.
I have been using this simple JavaScript helper for my tiny project and so far it seems to be light yet versatile enough to handle namespacing and loading modules/classes. It would be great if it would allow me to import a package into a namespace of my choice, not just the global namespace... sigh, but that's besides the point.
It allows you to declare the namespace then define objects/modules in that namespace:
Namespace('my.awesome.package');
my.awesome.package.WildClass = {};
Another option is to declare the namespace and its contents at once:
Namespace('my.awesome.package', {
SuperDuperClass: {
saveTheDay: function() {
alert('You are welcome.');
}
}
});
For more usage examples, look at the example.js file in the source.

Sample:
var namespace = {};
namespace.module1 = (function(){
var self = {};
self.initialized = false;
self.init = function(){
setTimeout(self.onTimeout, 1000)
};
self.onTimeout = function(){
alert('onTimeout')
self.initialized = true;
};
self.init(); /* If it needs to auto-initialize, */
/* You can also call 'namespace.module1.init();' from outside the module. */
return self;
})()
You can optionally declare a local variable, same, like self and assign local.onTimeout if you want it to be private.

The Module pattern was originally defined as a way to provide both private and public encapsulation for classes in conventional software engineering.
When working with the Module pattern, we may find it useful to define a simple template that we use for getting started with it. Here's one that covers name-spacing, public and private variables.
In JavaScript, the Module pattern is used to further emulate the concept of classes in such a way that we're able to include both public/private methods and variables inside a single object, thus shielding particular parts from the global scope. What this results in is a reduction in the likelihood of our function names conflicting with other functions defined in additional scripts on the page.
var myNamespace = (function () {
var myPrivateVar, myPrivateMethod;
// A private counter variable
myPrivateVar = 0;
// A private function which logs any arguments
myPrivateMethod = function( foo ) {
console.log( foo );
};
return {
// A public variable
myPublicVar: "foo",
// A public function utilizing privates
myPublicFunction: function( bar ) {
// Increment our private counter
myPrivateVar++;
// Call our private method using bar
myPrivateMethod( bar );
}
};
})();
Advantages
why is the Module pattern a good choice? For starters, it's a lot cleaner for developers coming from an object-oriented background than the idea of true encapsulation, at least from a JavaScript perspective.
Secondly, it supports private data - so, in the Module pattern, public parts of our code are able to touch the private parts, however the outside world is unable to touch the class's private parts.
Disadvantages
The disadvantages of the Module pattern are that as we access both public and private members differently, when we wish to change visibility, we actually have to make changes to each place the member was used.
We also can't access private members in methods that are added to the object at a later point. That said, in many cases the Module pattern is still quite useful and when used correctly, certainly has the potential to improve the structure of our application.
The Revealing Module Pattern
Now that we're a little more familiar with the module pattern, let’s take a look at a slightly improved version - Christian Heilmann’s Revealing Module pattern.
The Revealing Module pattern came about as Heilmann was frustrated with the fact that he had to repeat the name of the main object when we wanted to call one public method from another or access public variables.He also disliked the Module pattern’s requirement for having to switch to object literal notation for the things he wished to make public.
The result of his efforts was an updated pattern where we would simply define all of our functions and variables in the private scope and return an anonymous object with pointers to the private functionality we wished to reveal as public.
An example of how to use the Revealing Module pattern can be found below
var myRevealingModule = (function () {
var privateVar = "Ben Cherry",
publicVar = "Hey there!";
function privateFunction() {
console.log( "Name:" + privateVar );
}
function publicSetName( strName ) {
privateVar = strName;
}
function publicGetName() {
privateFunction();
}
// Reveal public pointers to
// private functions and properties
return {
setName: publicSetName,
greeting: publicVar,
getName: publicGetName
};
})();
myRevealingModule.setName( "Paul Kinlan" );
Advantages
This pattern allows the syntax of our scripts to be more consistent. It also makes it more clear at the end of the module which of our functions and variables may be accessed publicly which eases readability.
Disadvantages
A disadvantage of this pattern is that if a private function refers to a public function, that public function can't be overridden if a patch is necessary. This is because the private function will continue to refer to the private implementation and the pattern doesn't apply to public members, only to functions.
Public object members which refer to private variables are also subject to the no-patch rule notes above.

If you need the private scope:
var yourNamespace = (function() {
//Private property
var publicScope = {};
//Private property
var privateProperty = "aaa";
//Public property
publicScope.publicProperty = "bbb";
//Public method
publicScope.publicMethod = function() {
this.privateMethod();
};
//Private method
function privateMethod() {
console.log(this.privateProperty);
}
//Return only the public parts
return publicScope;
}());
yourNamespace.publicMethod();
else if you won't ever use the private scope:
var yourNamespace = {};
yourNamespace.publicMethod = function() {
// Do something...
};
yourNamespace.publicMethod2 = function() {
// Do something...
};
yourNamespace.publicMethod();

You can declare a simple function to provide namespaces.
function namespace(namespace) {
var object = this, tokens = namespace.split("."), token;
while (tokens.length > 0) {
token = tokens.shift();
if (typeof object[token] === "undefined") {
object[token] = {};
}
object = object[token];
}
return object;
}
// Usage example
namespace("foo.bar").baz = "I'm a value!";

I'm 7 years late to the party, but did quite a bit of work around this 8 years ago:
http://blogger.ziesemer.com/2008/05/javascript-namespace-function.html
http://blogger.ziesemer.com/2007/10/respecting-javascript-global-namespace.html
It is important to be able to easily and efficiently create multiple nested namespaces to keep a complex web application organized and manageable, while respecting the JavaScript global namespace (preventing namespace pollution), and with not clobbering any existing objects in the namespace path while doing so.
From the above, this was my circa-2008 solution:
var namespace = function(name, separator, container){
var ns = name.split(separator || '.'),
o = container || window,
i,
len;
for(i = 0, len = ns.length; i < len; i++){
o = o[ns[i]] = o[ns[i]] || {};
}
return o;
};
This isn't creating a namespace, but provides a function for creating namespaces.
This can be condensed to a minified one-liner:
var namespace=function(c,f,b){var e=c.split(f||"."),g=b||window,d,a;for(d=0,a=e.length;d<a;d++){g=g[e[d]]=g[e[d]]||{}}return g};
Example of use:
namespace("com.example.namespace");
com.example.namespace.test = function(){
alert("In namespaced function.");
};
Or, as one statement:
namespace("com.example.namespace").test = function(){
alert("In namespaced function.");
};
Either is then executed as:
com.example.namespace.test();
If you don't need support for legacy browsers, an updated version:
const namespace = function(name, separator, container){
var o = container || window;
name.split(separator || '.').forEach(function(x){
o = o[x] = o[x] || {};
});
return o;
};
Now, I'd be leery of exposing namespace to the global namespace itself. (Too bad the base language doesn't provide this for us!) So I'd typically use this myself in a closure, such as:
(function(){
const namespace = function(name, separator, container){
var o = container || window;
name.split(separator || '.').forEach(function(x){
o = o[x] = o[x] || {};
});
return o;
};
const ns = namespace("com.ziesemer.myApp");
// Optional:
ns.namespace = ns;
// Further extend, work with ns from here...
}());
console.log("\"com\":", com);
In a larger application, this only needs to be defined once at the beginning of a page load (for client-based web apps). Additional files can then reuse the namespace function if kept (included as "optional" in the above). At worst, if this function is re-declared a few times - it's only a few lines of code, and less if minified.

I created namespace which is inspired by Erlang's modules. It is a very functional approach, but that is how I write my JavaScript code these days.
It gives a closure a global namespace and exposes a defined set functions within that closure.
(function(){
namespace("images", previous, next);
// ^^ This creates or finds a root object, images, and binds the two functions to it.
// It works even though those functions are not yet defined.
function previous(){ ... }
function next(){ ... }
function find(){ ... } // A private function
})();

After porting several of my libraries to different projects, and having to constantly be changing the top level (statically named) namespace, I've switched to using this small (open source) helper function for defining namespaces.
global_namespace.Define('startpad.base', function(ns) {
var Other = ns.Import('startpad.other');
....
});
Description of the benefits are at my blog post. You can grab the source code here.
One of the benefits I really like is isolation between modules with respect to load order. You can refer to an external module BEFORE it is loaded. And the object reference you get will be filled in when the code is available.

I use the following syntax for the namespace.
var MYNamespace = MYNamespace|| {};
MYNamespace.MyFirstClass = function (val) {
this.value = val;
this.getValue = function(){
return this.value;
};
}
var myFirstInstance = new MYNamespace.MyFirstClass(46);
alert(myFirstInstance.getValue());
jsfiddle: http://jsfiddle.net/rpaul/4dngxwb3/1/

I think you all use too much code for such a simple problem.
No need to make a repo for that.
Here's a single line function.
namespace => namespace.split(".").reduce((last, next) => (last[next] = (last[next] || {})), window);
Try it :
// --- definition ---
const namespace = name => name.split(".").reduce((last, next) => (last[next] = (last[next] || {})), window);
// --- Use ----
const c = namespace("a.b.c");
c.MyClass = class MyClass {};
// --- see ----
console.log("a : ", a);

ES6 Modules Namespace imports
// circle.js
export { name, draw, reportArea, reportPerimeter };
// main.js
import * as Circle from './modules/circle.js';
// draw a circle
let circle1 = Circle.draw(myCanvas.ctx, 75, 200, 100, 'green');
Circle.reportArea(circle1.radius, reportList);
Circle.reportPerimeter(circle1.radius, reportList);
This grabs all the exports available inside circle.js, and makes them available as members of an object Circle, effectively giving it its own namespace.

My favorite pattern has become lately this:
var namespace = (function() {
// expose to public
return {
a: internalA,
c: internalC
}
// all private
/**
* Full JSDoc
*/
function internalA() {
// ...
}
/**
* Full JSDoc
*/
function internalB() {
// ...
}
/**
* Full JSDoc
*/
function internalC() {
// ...
}
/**
* Full JSDoc
*/
function internalD() {
// ...
}
})();
Of course, return can be at the end, but if only function declarations follow it, it's much easier to see what's the namespace all about, and what API is exposed.
The pattern of using function expressions in such cases results in not being able to know what methods are exposed without going over the entire code.

I like Jaco Pretorius' solution, but I wanted to make the "this" keyword a bit more useful by pointing it to the module/namespace object.
My version of skillet:
(function ($, undefined) {
console.log(this);
}).call(window.myNamespace = window.myNamespace || {}, jQuery);

JavaScript does not yet have a native representation of namespaces, but TypeScript does.
For example, you could use the following TS code (playground)
namespace Stack {
export const hello = () => console.log('hi')
}
Stack.hello()
If you can't update your code to TS, you can at least use the pattern employed by TS when generating the JS output for namespaces, which looks like this:
var Stack;
(function (Stack) {
Stack.hello = () => console.log('hi');
})(Stack || (Stack = {}));
Stack.hello();
Further Reading:
TS - Namespaces
TS - Namespaces and Modules

If using a Makefile you can do this.
// prelude.hjs
billy = new (
function moduleWrapper () {
const exports = this;
// postlude.hjs
return exports;
})();
// someinternalfile.js
function bob () { console.log('hi'); }
exports.bob = bob;
// clientfile.js
billy.bob();
I prefer to use a Makefile anyway once I get to about 1000 lines because I can effectively comment out large swaths of code by removing a single line in the makefile. It makes it easy to fiddle with stuff. Also, with this technique the namespace only appears once in the prelude so it's easy to change and you don't have to keep repeating it inside the library code.
A shell script for live development in the browser when using a makefile:
while (true); do make; sleep 1; done
Add this as a make task 'go' and you can 'make go' to keep your build updated as you code.

Quite a follow-up of Ionuț G. Stan's answer, but showing the benefits of uncluttered code by using var ClassFirst = this.ClassFirst = function() {...}, which takes advantage of JavaScript's closure scoping for less namespace cluttering for classes in the same namespace.
var Namespace = new function() {
var ClassFirst = this.ClassFirst = function() {
this.abc = 123;
}
var ClassSecond = this.ClassSecond = function() {
console.log("Cluttered way to access another class in namespace: ", new Namespace.ClassFirst().abc);
console.log("Nicer way to access a class in same namespace: ", new ClassFirst().abc);
}
}
var Namespace2 = new function() {
var ClassFirst = this.ClassFirst = function() {
this.abc = 666;
}
var ClassSecond = this.ClassSecond = function() {
console.log("Cluttered way to access another class in namespace: ", new Namespace2.ClassFirst().abc);
console.log("Nicer way to access a class in same namespace: ", new ClassFirst().abc);
}
}
new Namespace.ClassSecond()
new Namespace2.ClassSecond()
Output:
Cluttered way to access another class in namespace: 123
Nicer way to access a class in same namespace: 123
Cluttered way to access another class in namespace: 666
Nicer way to access a class in same namespace: 666

I've written another namespacing library that works a bit more like packages / units do in other languages. It allows you to create a package of JavaScript code and the reference that package from other code:
File hello.js
Package("hello", [], function() {
function greeting() {
alert("Hello World!");
}
// Expose function greeting to other packages
Export("greeting", greeting);
});
File Example.js
Package("example", ["hello"], function(greeting) {
// Greeting is available here
greeting(); // Alerts: "Hello World!"
});
Only the second file needs to be included in the page. Its dependencies (file hello.js in this example) will automatically be loaded and the objects exported from those dependencies will be used to populate the arguments of the callback function.
You can find the related project in Packages JS.

We can use it independently in this way:
var A = A|| {};
A.B = {};
A.B = {
itemOne: null,
itemTwo: null,
};
A.B.itemOne = function () {
//..
}
A.B.itemTwo = function () {
//..
}

In JavaScript there are no predefined methods to use namespaces. In JavaScript we have to create our own methods to define NameSpaces. Here is a procedure we follow in Oodles technologies.
Register a NameSpace
Following is the function to register a name space
//Register NameSpaces Function
function registerNS(args){
var nameSpaceParts = args.split(".");
var root = window;
for(var i=0; i < nameSpaceParts.length; i++)
{
if(typeof root[nameSpaceParts[i]] == "undefined")
root[nameSpaceParts[i]] = new Object();
root = root[nameSpaceParts[i]];
}
}
To register a Namespace just call the above function with the argument as name space separated by '.' (dot).
For Example
Let your application name is oodles. You can make a namespace by following method
registerNS("oodles.HomeUtilities");
registerNS("oodles.GlobalUtilities");
var $OHU = oodles.HomeUtilities;
var $OGU = oodles.GlobalUtilities;
Basically it will create your NameSpaces structure like below in backend:
var oodles = {
"HomeUtilities": {},
"GlobalUtilities": {}
};
In the above function you have register a namespace called "oodles.HomeUtilities" and "oodles.GlobalUtilities". To call these namespaces we make an variable i.e. var $OHU and var $OGU.
These variables are nothing but an alias to Intializing the namespace.
Now, Whenever you declare a function that belong to HomeUtilities you will declare it like following:
$OHU.initialization = function(){
//Your Code Here
};
Above is the function name initialization and it is put into an namespace $OHU. and to call this function anywhere in the script files. Just use following code.
$OHU.initialization();
Similarly, with the another NameSpaces.
Hope it helps.

My habit is to use function myName() as property storage, and then var myName as "method" holder...
Whether this is legitimate enough or not, beat me! I am relying on my PHP logic all the time, and things simply work. :D
function myObj() {
this.prop1 = 1;
this.prop2 = 2;
this.prop3 = 'string';
}
var myObj = (
(myObj instanceof Function !== false)
? Object.create({
$props: new myObj(),
fName1: function() { /* code.. */ },
fName2: function() { /* code ...*/ }
})
: console.log('Object creation failed!')
);
if (this !== that) myObj.fName1(); else myObj.fName2();
You can also do it in a 'vice versa' way to check before object creation which is much better:
function myObj() {
this.prop1 = 1;
this.prop2 = 2;
this.prop3 = 'string';
}
var myObj = (
(typeof(myObj) !== "function" || myObj instanceof Function === false)
? new Boolean()
: Object.create({
$props: new myObj(),
init: function () { return; },
fName1: function() { /* code.. */ },
fName2: function() { /* code ...*/ }
})
);
if (myObj instanceof Boolean) {
Object.freeze(myObj);
console.log('myObj failed!');
debugger;
}
else
myObj.init();
Reference to this: JavaScript: Creating Object with Object.create()

JavaScript doesn’t support namespace by default. So if you create any element(function, method, object, variable) then it becomes global and pollute the global namespace. Let's take an example of defining two functions without any namespace,
function func1() {
console.log("This is a first definition");
}
function func1() {
console.log("This is a second definition");
}
func1(); // This is a second definition
It always calls the second function definition. In this case, namespace will solve the name collision problem.

Related

Private prototype methods that can share scope and access the instance

I'm looking for a pattern that both allows me to create a private scope that my function prototype has access to and I need to be able to access the instance from within that scope.
For example, this is how I am currently achieving "private methods" (disregard what the code actually does, just look at the structure.)
function InfoPreview() {
this.element = document.createElement('div');
}
//Private Methods
InfoPreview.prototype.__newLine = function () {
this.element.appendChild(createElement({tagName:'br'}));
};
InfoPreview.prototype.__padLeft = function(level) {
var padding = createElement({tagName: 'span'});
this.element.appendChild(padding);
$(padding).width(level * 10);
};
InfoPreview.prototype.__print = function(string) {
var span = createElement({ tagName: 'span', textContent: string });
this.element.appendChild(span);
this.element.style["margin-right"]='10px';
};
InfoPreview.prototype.__puts = function(string) {
this.__print(string);
this.__newLine();
};
//Public Methods
InfoPreview.prototype.update = function(info) {
$(this.element).empty();
for (var record in info) {
this.__puts(record);
}
};
Notice that I am not creating private methods at all, just utilizing a naming convention. Additionally notice that I have no way to cache chain-lookups, such as this.element.
I would like to create a private scope by utilizing a revealing module pattern, like this:
InfoPreview.prototype = (function() {
var self = this, //<- `this` is actually the global object now.
el = self.element;
var newLine = function () {
el.appendChild(createElement({tagName:'br'}));
};
var padLeft = function(level) {
var padding = createElement({tagName: 'span'});
el.appendChild(padding);
$(padding).width(level * 10);
};
var print = function(string) {
var span = createElement({ tagName: 'span', textContent: string });
el.appendChild(span);
el.style["margin-right"]='10px';
};
var puts = function(string) {
print(string);
newLine();
};
var update = function(info) {
$(el).empty();
for (var record in info) {
puts(record);
}
};
return {
update: update
};
})();
The above approach doesn't work however, because the value of this within the IIFE is the global object, not the instance. I need a way to access the instance.
Is there any downside of using a constructor pattern?
function Foo(constructorArg) {
/* private variables */
var privVar = 'I am private',
cArg = constructorArg;
/* public variables */
this.pubVar = 'I am public';
/* private function */
function privFunc() {
return 'I am a private function';
}
/* public function */
this.publicFunc = function() {
return 'I am a public function and I call privVar->"' + privVar + '" and privFunc->"' + privFunc() + '"';
}
}
var foo = new Foo('something');
console.log('foo.pubVar', foo.pubVar); //ok
console.log('foo.publicFunc()', foo.publicFunc()); // ok
console.log('foo.privVar', foo.privVar); // undefined
console.log('foo.privFunc', foo.privFunc()); //error
Why you should use it (as requested in comments):
Simply put, because it is the only (sane) way of creating a "true private scope", which was your question.
The alternative is using a convention which tell developers what properties and methods are private, usually by prefixing them with an underscore _, which you already implemented but disliked.
Note that constructor and prototype are different things and enable you to do different stuff. Nothing prevents you from mixing both up.
Memory usage
Regarding memory usage, in modern js engines, such as Google's V8 JavaScript Engine, the constructor pattern might actually be faster.
V8 has hidden types created internally for objects at runtime; objects with the same hidden class can then use the same optimized generated code.
For example:
function Point(x, y) {
this.x = x;
this.y = y;
}
var p1 = new Point(11, 22);
var p2 = new Point(33, 44);
// At this point, p1 and p2 have a shared hidden class
p2.z = 55;
// warning! p1 and p2 now have different hidden classes!
Prototype chaining always require two lookups, so it might even be a tiny inny LITTLE bit slower. Note: Can't back up on this, jsperf.com is down!
Constructor pattern is dirty (sic)
Performance was my reason. I hadn't realized that. However it still feels dirty to me
I don't know why you feel the constructor pattern is dirty. Maybe it's because it has some "specifics", limitations and potential pitfalls you should be aware
this can mean different things
It's easy to forget the new keyword causing weird and hard to debug bugs due to shared state
You can't easily split your object across multiple files (without resorting to a build tool or some 3rd party injector)
However, 1 and 2 are also true for prototype declaration style so...
if you feel this is not adequate, you might want to look at the module pattern.
Within each function, you will have access to the this value you want.
var Example = function() {};
Example.prototype = (function() {
var privateUpdate = function() {
document.getElementById('answer').innerHTML = this.foo;
}
return {
update: privateUpdate
}
})();
var e = new Example();
e.foo = 'bar';
e.update();
<div id="answer"></div>
As a variant on what Pointy is suggesting, you can try this pattern;
infoPreview.prototype = (function() {
var self = null;
var update = function(info) {
....
};
var firstUpdate = function(info) {
self = this;
functions.update = update;
update(info);
}
var functions = {
update: firstUpdate
};
return functions;
})();
Maybe something like that, without prototyping :
https://jsfiddle.net/ynwun1xb
var Fn = function(el) {
this.el = el;
var myMethod = function() {
console.log('do something in method with element', this.el);
}.bind(this);
return {
myPublicMethod: function() {
return myMethod();
}
}
}
var instancedFn = new Fn('first instance element')
.myPublicMethod()
;
var instancedFn2 = new Fn('second instance element')
.myPublicMethod()
;

Javascript OOP - private/public methods [duplicate]

To make a JavaScript class with a public method I'd do something like:
function Restaurant() {}
Restaurant.prototype.buy_food = function(){
// something here
}
Restaurant.prototype.use_restroom = function(){
// something here
}
That way users of my class can:
var restaurant = new Restaurant();
restaurant.buy_food();
restaurant.use_restroom();
How do I create a private method that can be called by the buy_food and use_restroom methods but not externally by users of the class?
In other words, I want my method implementation to be able to do:
Restaurant.prototype.use_restroom = function() {
this.private_stuff();
}
But this shouldn't work:
var r = new Restaurant();
r.private_stuff();
How do I define private_stuff as a private method so both of these hold true?
I've read Doug Crockford's writeup a few times but it doesn't seem like "private" methods can be called by public methods and "privileged" methods can be called externally.
You can do it, but the downside is that it can't be part of the prototype:
function Restaurant() {
var myPrivateVar;
var private_stuff = function() { // Only visible inside Restaurant()
myPrivateVar = "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
private_stuff();
}
}
Using self invoking function and call
JavaScript uses prototypes and does't have classes (or methods for that matter) like Object Oriented languages. A JavaScript developer need to think in JavaScript.
Wikipedia quote:
Unlike many object-oriented languages, there is no distinction between
a function definition and a method definition. Rather, the distinction
occurs during function calling; when a function is called as a method
of an object, the function's local this keyword is bound to that
object for that invocation.
Solution using a self invoking function and the call function to call the private "method" :
var MyObject = (function () {
// Constructor
function MyObject(foo) {
this._foo = foo;
}
function privateFun(prefix) {
return prefix + this._foo;
}
MyObject.prototype.publicFun = function () {
return privateFun.call(this, ">>");
}
return MyObject;
}());
var myObject = new MyObject("bar");
myObject.publicFun(); // Returns ">>bar"
myObject.privateFun(">>"); // ReferenceError: private is not defined
The call function allows us to call the private function with the appropriate context (this).
Simpler with Node.js
If you are using Node.js, you don't need the IIFE because you can take advantage of the module loading system:
function MyObject(foo) {
this._foo = foo;
}
function privateFun(prefix) {
return prefix + this._foo;
}
MyObject.prototype.publicFun = function () {
return privateFun.call(this, ">>");
}
module.exports= MyObject;
Load the file:
var MyObject = require("./MyObject");
var myObject = new MyObject("bar");
myObject.publicFun(); // Returns ">>bar"
myObject.privateFun(">>"); // ReferenceError: private is not defined
(new!) Native private methods in future JavaScript versions
TC39 private methods and getter/setters for JavaScript classes proposal is stage 3. That means any time soon, JavaScript will implement private methods natively!
Note that JavaScript private class fields already exists in modern JavaScript versions.
Here is an example of how it is used:
class MyObject {
// Private field
#foo;
constructor(foo) {
this.#foo = foo;
}
#privateFun(prefix) {
return prefix + this.#foo;
}
publicFun() {
return this.#privateFun(">>");
}
}
You may need a JavaScript transpiler/compiler to run this code on old JavaScript engines.
PS: If you wonder why the # prefix, read this.
(deprecated) ES7 with the Bind Operator
Warning: The bind operator TC39 proposition is near dead https://github.com/tc39/proposal-bind-operator/issues/53#issuecomment-374271822
The bind operator :: is an ECMAScript proposal and is implemented in Babel (stage 0).
export default class MyObject {
constructor (foo) {
this._foo = foo;
}
publicFun () {
return this::privateFun(">>");
}
}
function privateFun (prefix) {
return prefix + this._foo;
}
You can simulate private methods like this:
function Restaurant() {
}
Restaurant.prototype = (function() {
var private_stuff = function() {
// Private code here
};
return {
constructor:Restaurant,
use_restroom:function() {
private_stuff();
}
};
})();
var r = new Restaurant();
// This will work:
r.use_restroom();
// This will cause an error:
r.private_stuff();
More information on this technique here: http://webreflection.blogspot.com/2008/04/natural-javascript-private-methods.html
In these situations when you have a public API, and you would like private and public methods/properties, I always use the Module Pattern. This pattern was made popular within the YUI library, and the details can be found here:
http://yuiblog.com/blog/2007/06/12/module-pattern/
It is really straightforward, and easy for other developers to comprehend. For a simple example:
var MYLIB = function() {
var aPrivateProperty = true;
var aPrivateMethod = function() {
// some code here...
};
return {
aPublicMethod : function() {
aPrivateMethod(); // okay
// some code here...
},
aPublicProperty : true
};
}();
MYLIB.aPrivateMethod() // not okay
MYLIB.aPublicMethod() // okay
Here is the class which I created to understand what Douglas Crockford's has suggested in his site Private Members in JavaScript
function Employee(id, name) { //Constructor
//Public member variables
this.id = id;
this.name = name;
//Private member variables
var fName;
var lName;
var that = this;
//By convention, we create a private variable 'that'. This is used to
//make the object available to the private methods.
//Private function
function setFName(pfname) {
fName = pfname;
alert('setFName called');
}
//Privileged function
this.setLName = function (plName, pfname) {
lName = plName; //Has access to private variables
setFName(pfname); //Has access to private function
alert('setLName called ' + this.id); //Has access to member variables
}
//Another privileged member has access to both member variables and private variables
//Note access of this.dataOfBirth created by public member setDateOfBirth
this.toString = function () {
return 'toString called ' + this.id + ' ' + this.name + ' ' + fName + ' ' + lName + ' ' + this.dataOfBirth;
}
}
//Public function has access to member variable and can create on too but does not have access to private variable
Employee.prototype.setDateOfBirth = function (dob) {
alert('setDateOfBirth called ' + this.id);
this.dataOfBirth = dob; //Creates new public member note this is accessed by toString
//alert(fName); //Does not have access to private member
}
$(document).ready()
{
var employee = new Employee(5, 'Shyam'); //Create a new object and initialize it with constructor
employee.setLName('Bhaskar', 'Ram'); //Call privileged function
employee.setDateOfBirth('1/1/2000'); //Call public function
employee.id = 9; //Set up member value
//employee.setFName('Ram'); //can not call Private Privileged method
alert(employee.toString()); //See the changed object
}
ES12 Private Methods
You can do this now with es12 private methods. You just need to add a # before the method name.
class ClassWithPrivateMethod {
#privateMethod() {
return 'hello world';
}
getPrivateMessage() {
return #privateMethod();
}
}
I conjured up this: EDIT: Actually, someone has linked to a identical solution. Duh!
var Car = function() {
}
Car.prototype = (function() {
var hotWire = function() {
// Private code *with* access to public properties through 'this'
alert( this.drive() ); // Alerts 'Vroom!'
}
return {
steal: function() {
hotWire.call( this ); // Call a private method
},
drive: function() {
return 'Vroom!';
}
};
})();
var getAwayVechile = new Car();
hotWire(); // Not allowed
getAwayVechile.hotWire(); // Not allowed
getAwayVechile.steal(); // Alerts 'Vroom!'
ES2021 / ES12 - Private Methods
Private method names start with a hash # prefix and can be accessed only inside the class where it is defined.
class Restaurant {
// private method
#private_stuff() {
console.log("private stuff");
}
// public method
buy_food() {
this.#private_stuff();
}
};
const restaurant = new Restaurant();
restaurant.buy_food(); // "private stuff";
restaurant.private_stuff(); // Uncaught TypeError: restaurant.private_stuff is not a function
I think such questions come up again and again because of the lack of understanding of the closures. Сlosures is most important thing in JS. Every JS programmer have to feel the essence of it.
1. First of all we need to make separate scope (closure).
function () {
}
2. In this area, we can do whatever we want. And no one will know about it.
function () {
var name,
secretSkills = {
pizza: function () { return new Pizza() },
sushi: function () { return new Sushi() }
}
function Restaurant(_name) {
name = _name
}
Restaurant.prototype.getFood = function (name) {
return name in secretSkills ? secretSkills[name]() : null
}
}
3. For the world to know about our restaurant class,
we have to return it from the closure.
var Restaurant = (function () {
// Restaurant definition
return Restaurant
})()
4. At the end, we have:
var Restaurant = (function () {
var name,
secretSkills = {
pizza: function () { return new Pizza() },
sushi: function () { return new Sushi() }
}
function Restaurant(_name) {
name = _name
}
Restaurant.prototype.getFood = function (name) {
return name in secretSkills ? secretSkills[name]() : null
}
return Restaurant
})()
5. Also, this approach has potential for inheritance and templating
// Abstract class
function AbstractRestaurant(skills) {
var name
function Restaurant(_name) {
name = _name
}
Restaurant.prototype.getFood = function (name) {
return skills && name in skills ? skills[name]() : null
}
return Restaurant
}
// Concrete classes
SushiRestaurant = AbstractRestaurant({
sushi: function() { return new Sushi() }
})
PizzaRestaurant = AbstractRestaurant({
pizza: function() { return new Pizza() }
})
var r1 = new SushiRestaurant('Yo! Sushi'),
r2 = new PizzaRestaurant('Dominos Pizza')
r1.getFood('sushi')
r2.getFood('pizza')
I hope this helps someone better understand this subject
Personally, I prefer the following pattern for creating classes in JavaScript :
var myClass = (function() {
// Private class properties go here
var blueprint = function() {
// Private instance properties go here
...
};
blueprint.prototype = {
// Public class properties go here
...
};
return {
// Public class properties go here
create : function() { return new blueprint(); }
...
};
})();
As you can see, it allows you to define both class properties and instance properties, each of which can be public and private.
Demo
var Restaurant = function() {
var totalfoodcount = 0; // Private class property
var totalrestroomcount = 0; // Private class property
var Restaurant = function(name){
var foodcount = 0; // Private instance property
var restroomcount = 0; // Private instance property
this.name = name
this.incrementFoodCount = function() {
foodcount++;
totalfoodcount++;
this.printStatus();
};
this.incrementRestroomCount = function() {
restroomcount++;
totalrestroomcount++;
this.printStatus();
};
this.getRestroomCount = function() {
return restroomcount;
},
this.getFoodCount = function() {
return foodcount;
}
};
Restaurant.prototype = {
name : '',
buy_food : function(){
this.incrementFoodCount();
},
use_restroom : function(){
this.incrementRestroomCount();
},
getTotalRestroomCount : function() {
return totalrestroomcount;
},
getTotalFoodCount : function() {
return totalfoodcount;
},
printStatus : function() {
document.body.innerHTML
+= '<h3>Buying food at '+this.name+'</h3>'
+ '<ul>'
+ '<li>Restroom count at ' + this.name + ' : '+ this.getRestroomCount() + '</li>'
+ '<li>Food count at ' + this.name + ' : ' + this.getFoodCount() + '</li>'
+ '<li>Total restroom count : '+ this.getTotalRestroomCount() + '</li>'
+ '<li>Total food count : '+ this.getTotalFoodCount() + '</li>'
+ '</ul>';
}
};
return { // Singleton public properties
create : function(name) {
return new Restaurant(name);
},
printStatus : function() {
document.body.innerHTML
+= '<hr />'
+ '<h3>Overview</h3>'
+ '<ul>'
+ '<li>Total restroom count : '+ Restaurant.prototype.getTotalRestroomCount() + '</li>'
+ '<li>Total food count : '+ Restaurant.prototype.getTotalFoodCount() + '</li>'
+ '</ul>'
+ '<hr />';
}
};
}();
var Wendys = Restaurant.create("Wendy's");
var McDonalds = Restaurant.create("McDonald's");
var KFC = Restaurant.create("KFC");
var BurgerKing = Restaurant.create("Burger King");
Restaurant.printStatus();
Wendys.buy_food();
Wendys.use_restroom();
KFC.use_restroom();
KFC.use_restroom();
Wendys.use_restroom();
McDonalds.buy_food();
BurgerKing.buy_food();
Restaurant.printStatus();
BurgerKing.buy_food();
Wendys.use_restroom();
McDonalds.buy_food();
KFC.buy_food();
Wendys.buy_food();
BurgerKing.buy_food();
McDonalds.buy_food();
Restaurant.printStatus();
See also this Fiddle.
All of this closure will cost you. Make sure you test the speed implications especially in IE. You will find you are better off with a naming convention. There are still a lot of corporate web users out there that are forced to use IE6...
Don't be so verbose. It's Javascript. Use a Naming Convention.
After years of working in es6 classes, I recently started work on an es5 project (using requireJS which is already very verbose-looking). I've been over and over all the strategies mentioned here and it all basically boils down to use a naming convention:
Javascript doesn't have scope keywords like private. Other developers entering Javascript will know this upfront. Therefore, a simple naming convention is more than sufficient. A simple naming convention of prefixing with an underscore solves the problem of both private properties and private methods.
Let's take advantage of the Prototype for speed reasons, but lets not get anymore verbose than that. Let's try to keep the es5 "class" looking as closely to what we might expect in other backend languages (and treat every file as a class, even if we don't need to return an instance).
Let's demonstrate with a more realistic module situation (we'll use old es5 and old requireJs).
my-tooltip.js
define([
'tooltip'
],
function(
tooltip
){
function MyTooltip() {
// Later, if needed, we can remove the underscore on some
// of these (make public) and allow clients of our class
// to set them.
this._selector = "#my-tooltip"
this._template = 'Hello from inside my tooltip!';
this._initTooltip();
}
MyTooltip.prototype = {
constructor: MyTooltip,
_initTooltip: function () {
new tooltip.tooltip(this._selector, {
content: this._template,
closeOnClick: true,
closeButton: true
});
}
}
return {
init: function init() {
new MyTooltip(); // <-- Our constructor adds our tooltip to the DOM so not much we need to do after instantiation.
}
// You could instead return a new instantiation,
// if later you do more with this class.
/*
create: function create() {
return new MyTooltip();
}
*/
}
});
Take any of the solutions that follow Crockford's private or priviledged pattern. For example:
function Foo(x) {
var y = 5;
var bar = function() {
return y * x;
};
this.public = function(z) {
return bar() + x * z;
};
}
In any case where the attacker has no "execute" right on the JS context he has no way of accessing any "public" or "private" fields or methods. In case the attacker does have that access he can execute this one-liner:
eval("Foo = " + Foo.toString().replace(
/{/, "{ this.eval = function(code) { return eval(code); }; "
));
Note that the above code is generic to all constructor-type-privacy. It will fail with some of the solutions here but it should be clear that pretty much all of the closure based solutions can be broken like this with different replace() parameters.
After this is executed any object created with new Foo() is going to have an eval method which can be called to return or change values or methods defined in the constructor's closure, e.g.:
f = new Foo(99);
f.eval("x");
f.eval("y");
f.eval("x = 8");
The only problem I can see with this that it won't work for cases where there is only one instance and it's created on load. But then there is no reason to actually define a prototype and in that case the attacker can simply recreate the object instead of the constructor as long as he has a way of passing the same parameters (e.g. they are constant or calculated from available values).
In my opinion, this pretty much makes Crockford's solution useless. Since the "privacy" is easily broken the downsides of his solution (reduced readability & maintainability, decreased performance, increased memory) makes the "no privacy" prototype based method the better choice.
I do usually use leading underscores to mark __private and _protected methods and fields (Perl style), but the idea of having privacy in JavaScript just shows how it's a misunderstood language.
Therefore I disagree with Crockford except for his first sentence.
So how do you get real privacy in JS? Put everything that is required to be private on the server side and use JS to do AJAX calls.
The apotheosis of the Module Pattern: The Revealing Module Pattern
A neat little extension to a very robust pattern.
If you want the full range of public and private functions with the ability for public functions to access private functions, layout code for an object like this:
function MyObject(arg1, arg2, ...) {
//constructor code using constructor arguments...
//create/access public variables as
// this.var1 = foo;
//private variables
var v1;
var v2;
//private functions
function privateOne() {
}
function privateTwon() {
}
//public functions
MyObject.prototype.publicOne = function () {
};
MyObject.prototype.publicTwo = function () {
};
}
var TestClass = function( ) {
var privateProperty = 42;
function privateMethod( ) {
alert( "privateMethod, " + privateProperty );
}
this.public = {
constructor: TestClass,
publicProperty: 88,
publicMethod: function( ) {
alert( "publicMethod" );
privateMethod( );
}
};
};
TestClass.prototype = new TestClass( ).public;
var myTestClass = new TestClass( );
alert( myTestClass.publicProperty );
myTestClass.publicMethod( );
alert( myTestClass.privateMethod || "no privateMethod" );
Similar to georgebrock but a little less verbose (IMHO)
Any problems with doing it this way? (I haven't seen it anywhere)
edit: I realised this is kinda useless since every independent instantiation has its own copy of the public methods, thus undermining the use of the prototype.
Here's what i enjoyed the most so far regarding private/public methods/members and instantiation in javascript:
here is the article: http://www.sefol.com/?p=1090
and here is the example:
var Person = (function () {
//Immediately returns an anonymous function which builds our modules
return function (name, location) {
alert("createPerson called with " + name);
var localPrivateVar = name;
var localPublicVar = "A public variable";
var localPublicFunction = function () {
alert("PUBLIC Func called, private var is :" + localPrivateVar)
};
var localPrivateFunction = function () {
alert("PRIVATE Func called ")
};
var setName = function (name) {
localPrivateVar = name;
}
return {
publicVar: localPublicVar,
location: location,
publicFunction: localPublicFunction,
setName: setName
}
}
})();
//Request a Person instance - should print "createPerson called with ben"
var x = Person("ben", "germany");
//Request a Person instance - should print "createPerson called with candide"
var y = Person("candide", "belgium");
//Prints "ben"
x.publicFunction();
//Prints "candide"
y.publicFunction();
//Now call a public function which sets the value of a private variable in the x instance
x.setName("Ben 2");
//Shouldn't have changed this : prints "candide"
y.publicFunction();
//Should have changed this : prints "Ben 2"
x.publicFunction();
JSFiddle: http://jsfiddle.net/northkildonan/kopj3dt3/1/
The module pattern is right in most cases. But if you have thousands of instances, classes save memory. If saving memory is a concern and your objects contain a small amount of private data, but have a lot of public functions, then you'll want all public functions to live in the .prototype to save memory.
This is what I came up with:
var MyClass = (function () {
var secret = {}; // You can only getPriv() if you know this
function MyClass() {
var that = this, priv = {
foo: 0 // ... and other private values
};
that.getPriv = function (proof) {
return (proof === secret) && priv;
};
}
MyClass.prototype.inc = function () {
var priv = this.getPriv(secret);
priv.foo += 1;
return priv.foo;
};
return MyClass;
}());
var x = new MyClass();
x.inc(); // 1
x.inc(); // 2
The object priv contains private properties. It is accessible through the public function getPriv(), but this function returns false unless you pass it the secret, and this is only known inside the main closure.
What about this?
var Restaurant = (function() {
var _id = 0;
var privateVars = [];
function Restaurant(name) {
this.id = ++_id;
this.name = name;
privateVars[this.id] = {
cooked: []
};
}
Restaurant.prototype.cook = function (food) {
privateVars[this.id].cooked.push(food);
}
return Restaurant;
})();
Private variable lookup is impossible outside of the scope of the immediate function.
There is no duplication of functions, saving memory.
The downside is that the lookup of private variables is clunky privateVars[this.id].cooked is ridiculous to type. There is also an extra "id" variable.
Wrap all code in Anonymous Function: Then , all functions will be private ,ONLY functions attached to window object :
(function(w,nameSpacePrivate){
w.Person=function(name){
this.name=name;
return this;
};
w.Person.prototype.profilePublic=function(){
return nameSpacePrivate.profile.call(this);
};
nameSpacePrivate.profile=function(){
return 'My name is '+this.name;
};
})(window,{});
Use this :
var abdennour=new Person('Abdennour');
abdennour.profilePublic();
FIDDLE
I prefer to store private data in an associated WeakMap. This allows you to keep your public methods on the prototype where they belong. This seems to be the most efficient way to handle this problem for large numbers of objects.
const data = new WeakMap();
function Foo(value) {
data.set(this, {value});
}
// public method accessing private value
Foo.prototype.accessValue = function() {
return data.get(this).value;
}
// private 'method' accessing private value
function accessValue(foo) {
return data.get(foo).value;
}
export {Foo};
2021 HERE!
This polyfill effectively hides your private properties and methods returning undefined when you try to read your private property and a TypeError when you try to execute your private method thus effectively making them both PRIVATE to the outside but giving you access to them by using your public methods.
If you check it you will see it is very easy to implement. For the most part you don't need to do anything quirky like using Proxy objects, underscore functions (_myprivate), getters or setters. None of that. The only thing required is to place in your constructor that like snippet of code that is aimed to let you expose your public interface to the outside world.
((self) => ({
pubProp: self.pubProp,
// More public properties to export HERE
// ...
pubMethod: self.pubMethod.bind(self)
// More public mehods to export HERE
// Be sure bind each of them to self!!!
// ...
}))(self);
The above code is where the magic happens. It is an IIFE that returns an object with just the properties and methods you want to exposed and bound to the context of the object that was first instantiated.
You can still access your hidden properties and methods but only through your public methods just the way OOP should do.
Consider that part of the code as your module.exports
BTW, this is without using the latest ECMAScript 2022 # addition to the language.
'use strict';
class MyClass {
constructor(pubProp) {
let self = this;
self.pubProp = pubProp;
self.privProp = "I'm a private property!";
return ((self) => ({
pubProp: self.pubProp,
// More public properties to export HERE
// ...
pubMethod: self.pubMethod.bind(self)
// More public mehods to export HERE
// Be sure to bind each of them to self!!!
// ...
}))(self);
}
pubMethod() {
console.log("I'm a public method!");
console.log(this.pubProp);
return this.privMethod();
}
privMethod() {
console.log("I'm a private method!");
return this.privProp
}
}
const myObj = new MyClass("I'm a public property!");
console.log("***DUMPING MY NEW INSTANCE***");
console.dir(myObj);
console.log("");
console.log("***TESTING ACCESS TO PUBLIC PROPERTIES***");
console.log(myObj.pubProp);
console.log("");
console.log("***TESTING ACCESS TO PRIVATE PROPERTIES***");
console.log(myObj.privProp);
console.log("");
console.log("***TESTING ACCESS TO PUBLIC METHODS***");
console.log("1. pubMethod access pubProp ");
console.log("2. pubMethod calls privMethod");
console.log("3. privMethod access privProp");
console.log("")
console.log(myObj.pubMethod());
console.log("");
console.log("***TESTING ACCESS TO PRIVATE METHODS***");
console.log(myObj.privMethod());
Check my gist
Private functions cannot access the public variables using module pattern
Since everybody was posting here his own code, I'm gonna do that too...
I like Crockford because he introduced real object oriented patterns in Javascript. But he also came up with a new misunderstanding, the "that" one.
So why is he using "that = this"? It has nothing to do with private functions at all. It has to do with inner functions!
Because according to Crockford this is buggy code:
Function Foo( ) {
this.bar = 0;
var foobar=function( ) {
alert(this.bar);
}
}
So he suggested doing this:
Function Foo( ) {
this.bar = 0;
that = this;
var foobar=function( ) {
alert(that.bar);
}
}
So as I said, I'm quite sure that Crockford was wrong his explanation about that and this (but his code is certainly correct). Or was he just fooling the Javascript world, to know who is copying his code? I dunno...I'm no browser geek ;D
EDIT
Ah, that's what is all about: What does 'var that = this;' mean in JavaScript?
So Crockie was really wrong with his explanation....but right with his code, so he's still a great guy. :))
In general I added the private Object _ temporarily to the object.
You have to open the privacy exlipcitly in the "Power-constructor" for the method.
If you call the method from the prototype, you will
be able to overwrite the prototype-method
Make a public method accessible in the "Power-constructor": (ctx is the object context)
ctx.test = GD.Fabric.open('test', GD.Test.prototype, ctx, _); // is a private object
Now I have this openPrivacy:
GD.Fabric.openPrivacy = function(func, clss, ctx, _) {
return function() {
ctx._ = _;
var res = clss[func].apply(ctx, arguments);
ctx._ = null;
return res;
};
};
This is what I worked out:
Needs one class of sugar code that you can find here. Also supports protected, inheritance, virtual, static stuff...
;( function class_Restaurant( namespace )
{
'use strict';
if( namespace[ "Restaurant" ] ) return // protect against double inclusions
namespace.Restaurant = Restaurant
var Static = TidBits.OoJs.setupClass( namespace, "Restaurant" )
// constructor
//
function Restaurant()
{
this.toilets = 3
this.Private( private_stuff )
return this.Public( buy_food, use_restroom )
}
function private_stuff(){ console.log( "There are", this.toilets, "toilets available") }
function buy_food (){ return "food" }
function use_restroom (){ this.private_stuff() }
})( window )
var chinese = new Restaurant
console.log( chinese.buy_food() ); // output: food
console.log( chinese.use_restroom() ); // output: There are 3 toilets available
console.log( chinese.toilets ); // output: undefined
console.log( chinese.private_stuff() ); // output: undefined
// and throws: TypeError: Object #<Restaurant> has no method 'private_stuff'
Class({
Namespace:ABC,
Name:"ClassL2",
Bases:[ABC.ClassTop],
Private:{
m_var:2
},
Protected:{
proval:2,
fight:Property(function(){
this.m_var--;
console.log("ClassL2::fight (m_var)" +this.m_var);
},[Property.Type.Virtual])
},
Public:{
Fight:function(){
console.log("ClassL2::Fight (m_var)"+this.m_var);
this.fight();
}
}
});
https://github.com/nooning/JSClass
I have created a new tool to allow you to have true private methods on the prototype
https://github.com/TremayneChrist/ProtectJS
Example:
var MyObject = (function () {
// Create the object
function MyObject() {}
// Add methods to the prototype
MyObject.prototype = {
// This is our public method
public: function () {
console.log('PUBLIC method has been called');
},
// This is our private method, using (_)
_private: function () {
console.log('PRIVATE method has been called');
}
}
return protect(MyObject);
})();
// Create an instance of the object
var mo = new MyObject();
// Call its methods
mo.public(); // Pass
mo._private(); // Fail
You have to put a closure around your actual constructor-function, where you can define your private methods.
To change data of the instances through these private methods, you have to give them "this" with them, either as an function argument or by calling this function with .apply(this) :
var Restaurant = (function(){
var private_buy_food = function(that){
that.data.soldFood = true;
}
var private_take_a_shit = function(){
this.data.isdirty = true;
}
// New Closure
function restaurant()
{
this.data = {
isdirty : false,
soldFood: false,
};
}
restaurant.prototype.buy_food = function()
{
private_buy_food(this);
}
restaurant.prototype.use_restroom = function()
{
private_take_a_shit.call(this);
}
return restaurant;
})()
// TEST:
var McDonalds = new Restaurant();
McDonalds.buy_food();
McDonalds.use_restroom();
console.log(McDonalds);
console.log(McDonalds.__proto__);
I know it's a bit too late but how about this?
var obj = function(){
var pr = "private";
var prt = Object.getPrototypeOf(this);
if(!prt.hasOwnProperty("showPrivate")){
prt.showPrivate = function(){
console.log(pr);
}
}
}
var i = new obj();
i.showPrivate();
console.log(i.hasOwnProperty("pr"));

Writing JS Prototypes, should all functions use the Prototype object?

I'm beginning to learn more about writing JS using the Prototype object, but I want to make sure I don't pick up any bad habits from other developers. My understanding of using Prototype is to create public methods for your instance. For example:
var module = new Module();
module.method();
But I see a lot of developers creating all their code inside the Prototype object, things that I would consider "private". Is this bad practice or considered okay? It just means I can then do:
module.privateFn();
Do they know this? Is that okay? Any help appreciated. I've been looking through the source code on GitHub to try establish the best way forward, here's a script that uses Prototypes for everything (for instance attachEvent which they clearly want privately kept):
https://github.com/WickyNilliams/headroom.js/blob/master/dist/headroom.js
Much appreciated, I want to make sure I develop using the correct implementations.
First of all you don't need to write modules using prototype. Think like if you writing something like a class you should use prototypes. And also it's important to where define your methods. Defining methods on prototype object and defining them in constructor function is totally different things!
Let's see a sample class definition with using methods defined in constructor:
var Dog = (function () {
var Dog = function (age, name) {
var that = this;
this.age = age;
this.name = name;
this.sayHi = function () {
console.log('Warf! Im ' + that.name); // meaning of "this" changed!!!
};
this.anotherMethod = function () {};
};
return Dog;
}());
var puppy = new Dog(1, 'puppy'); // sayHi and anotherMethod created
var sirius = new Dog(1, 'sirius'); // sayHi and anotherMethod recreated
sirius.sayHi = function () { console.log('Yohalolop!'); };
puppy.sayHi(); // -> 'Warf! Im puppy'
sirius.sayHi(); // -> 'Yohalolop!'
So there is some problems with the above example, firstly methods are defined like any other instance variables. Actually yeah you define them as instance variable and this means this functions are recreated for every instance object you create. I guess you have mentioned you can't use this keyword in your method definitions. This is error prone and there is a chance to forget that and use this keyword by mistaken. There are some times you can use methods as instance variables of course like variable callbacks.
Let's see a sample class definition with prototype object:
var Dog = (function () {
var Dog = function (age, name) {
this.age = age;
this.name = name;
};
// sayHi method defined only once in prototype
Dog.prototype.sayHi = function () {
console.log('Warf! Im ' + this.name; // we can use this keyword
};
// anotherMethod defined only once in protoype
Dog.prototype.anotherMethod() {
};
return Dog;
}());
var puppy = new Dog(1, 'puppy');
var sirius = new Dog(1, 'sirius'); // sirius and puppy sharing same prototype object
puppy.sayHi(); // -> 'Warf! Im puppy'
sirius.sayHi(); // -> 'Warf! Im sirius'
// remember puppy and sirius sharing same prototype object
Dog.prototype.sayHi = function () {
console.log('Yohalolop');
};
puppy.sayHi(); // -> 'Yohalolop'
sirius.sayHi(); // -> 'Yohalolop'
As an answer to your question about private functions, it is more complicated. Yes you can use private functions even you define your methods on prototype, but there are some concerns about testing. Usage of them is up to you. I prefer to don't use. Let me show some examples.
var Calculator = (function () {
var Calculator = function () {
this.importantNumber = 2;
};
// There is unfortunately no native implementation
// for private methods but you can mimic them with
// unaccessible functions and binding.
var someExtremeComputations = function () {
return 40 + this.importantNumber; // this keyword points to instance because of binding
};
Calculator.prototype.getMeaningOfLife = function () {
var result = someExtremeComputations.call(this); // we bind function to instance
return result;
};
return Calculator;
}());
This is the one of the examples how you can define private methods in javascript. The problem with private functions, they can't be tested. There is no way to test someExtremeComputations method.
Some people (includes me) use prefixed underscore naming convention for private methods. So they are actually public methods but if someone calling them or overriding they were warned by prefixed underscore. After all we can test private methods since they are public in real.
var Calculator = (function () {
var Calculator = function () {
this.importantNumber = 2;
};
// private method's name prefixed by an underscore to warn
// other developers to be careful about that or not to use.
Calculator.prototype._someExtremeComputations = function () {
return 40 + this.importantNumber;
};
Calculator.prototype.getMeaningOfLife = function () {
var result = this.someExtremeComputations(); // no need to bind
return result;
};
return Calculator;
}());
Explaining this with a few words is impossible. A generally good pattern is to construct methods through prototypes when you want to optimize your code. A good guideline is to only put the most essential data in the memory, using prototypes is critical for this since the prototyped variables and methods isn't injected into the memory until you request them.
When it comes yo your example there are no prototypes.
Simple example
// new object
var Dog = function() {
var that = this;
// add a property
that.name = "Fido";
// add a method
that.getName = function() {
return that.name;
};
};
// ... all the above is stored in memory directly
// Requires to be constructed
var dogObj = new Dog();
console.log(dogObj.getName()); // Fido
delete Dog.name // false
typeof Dog.name // "string"
delete dogObj.name // true
typeof dogObj.name // "undefined"
typeof Dog.name // "string" (still there)
// Will be available in the dogObj (after you call it)
dog.prototype.first = "first";
// Will be available in the dogObj (after you call it)
dog.prototype.second = function() {
return "second";
}
// Will not be available in dogObj
dog.third = "third";

Javascript mixins when using the module pattern

I've been using the module pattern for a while, but recently have started wanting to mix in functions and properties into them to increase code re-use. I've read some good resources on the subject, but still am a bit uncertain as to the best approach. Here is a module:
var myModule = function () {
var privateConfigVar = "Private!";
//"constructor"
function module() {}
module.publicMethod = function () {
console.log('public');
}
function privateMethod1() {
console.log('private');
}
return module;
}
And here is a mixin object:
var myMixin = function () {};
Mixin.prototype = {
mixinMethod1: function () {
console.log('mixin private 1');
},
mixinMethod2: function () {
console.log('mixin private 2');
}
};
Ideally, I'd like to mix-in some methods from other objects as private methods and some as public methods, so that I could call some "extend" function, with a param as "private"/"public". So, that
mixin(myModule, myMixin, "private");
makes the myMixin methods available within myModule by just calling mixinMethod1() and have correct scope, and:
mixin(myModule, myMixin, "public");
makes the myMixin methods available within myModule by calling module.mixinMethod1() and have correct scope
I've tried using a method that copies properties from one prototype to another, I've tried the underscore extend method to copy properties of the object from one to to the other, and various things in between. I think I'm a bit turned around regarding scope and prototypes at this point, and would love some direction as to how best to do mixins like this when using the module pattern. Note that it doesn't matter what the object myMixin looks like (whether adding functions to the prototype, or a module itself), I'm just trying to figure out some way to make it work.
Thank!
So that [some code] makes the myMixin methods available within myModule by just calling mixinMethod1() and have correct scope
That's impossible. You cannot modify a scope by calling a function, especially not from outside. See also Is it possible to import variables in JavaScript? for the design reasons of that.
So, what can you do?
From outside the module
Nothing to the private scope(s) of module functions. And you cannot use the private functions of the module, obviously. You can extend its prototype with methods (which is the most common), you can even decorate its constructor function. Within those, you can use your own private functions, either completely static ones or class-specific ones.
var myMixin = (function() {
// everything class-unspecific but mixin-local
var staticMixinVariables, …;
function globalPrivateFunction(){…}
function staticMethod(){…}
return function(mod) {
// everything class-specific
// also using the locals from above
mod.staticHelper = function() { staticMixinVariable … };
mod.prototype.mixinMethod1 = staticMethod;
mod.prototype.mixinMethod2 = function(){…};
…
};
})();
// Example:
myMixin(SomeClass)
From within the module
Using the mixin in the module code itself can allow for much greater flexibility.
var myMixin = (function() {
// everything class-unspecific but mixin-local
…
return {
publicHelper1: function(){…},
publicHelper2: function(){…},
decorateInstance: function(o) {
o.xy = …;
},
extendPrototype: function(proto) {
// everything class-specific
// also using the locals from above
proto.mixinMethod1 = staticMethod;
proto.mixinMethod2 = function(){…};
…
}
};
})();
With such an interface, it becomes easy to construct a class that is using this as a mixin (not inheriting from it):
var myClass = (function() {
function Constructor() {
myMixin.decorateInstance(this);
…
}
Constructor.prototype.method1 = function() { myMixin.publicHelper1() … };
Constructor.prototype.method2 = function() { … };
myMixin.extendPrototype(Constructor.prototype);
Constructor.myHelper = myMixin.publicHelper2; // re-export explicitly
return Constructor;
})();
However, the mixin will never have access to the private class variables, nor can it present a private, class-specific API. Still, we can use dependency injection to provide that access explicitly (and having a mixin factory in effect):
var myClass = (function() {
var … // private class functions and variables
var mixer = myMixin(privateClassHelper,
privateClassVariable,
function setPrivateVar(x) {…},
… );
var myHelper = mixer.customHelper, … // local "aliases"
function Constructor(localX) {
mixer.decorateInstance(this, localX);
…
}
… // further using the class-specific private mixer
return Constructor;
})();
Not all techniques shown above need to be used in every mixin, just choose the ones you need. Not all possible techniques are shown in the above examples, also :-) The mixin pattern can be applied onto a plain module or inside its declaration as well, the above examples have only shown classes with prototypes.
For a few good examples, and a theoretical distinction between (stateless) Traits, (stateful) Mixins and their "privileged" counterparts, have a look at this presentation.
The with keyword can be very usefull to define a scope, but it has also some drawbacks (it is by the way forbidden in strict mode).
Using the with keyword, you can define a private variable privateScope within the body of your module, that would contain all your provate methods :
var myModule = function () {
var privateConfigVar = "Private!";
var privateScope = {};
//"constructor"
function module() {}
var proto = module.prototype;//avoids multiple attribute lookup
//Let's re-define you example' private method, but with a new strategy
privateScope['privateMethod1'] = function() {
console.log('private');
}
proto.publicMethod = function () {
with(privateScope){
//this call should work
privateMethod1();
}
console.log('public');
}
proto.publicMethod2=function(name,fn){
with(privateScope){
//this will be defined later by a Mixin
otherPrivateMethod();
}
console.log('public2');
}
proto.definePrivateFunction=function(name,fn){
privateScope[name] = fn;
}
return module;
}
Your mixin will use the definePrivateFunction we just defined to add private methods to the private scope :
//An example mixin implementation
function Mixin(source,target,flag){
if(flag==="private"){
for(var currentMethodName in source){
target.definePrivateFunction(currentMethodName,source[currentMethod])
}
}else{
for(var currentMethodName in source){
target[currentMethodName]=source[currentMethod];
}
}
}
The following code should work fine:
var test = myModule();
var testInstance = new test();
testInstance.publicMethod();// will call the private method defined internally
Mixin({
otherPrivateMethod:function(){
console.log("other Prvate Method called")
}
},test.prototype,"private");
testInstance.publicMethod2();// will call the private method defined by the mixin
Ideally, I'd like to mix-in some methods from other objects as private methods and some as public methods, so that I could call some "extend" function, with a param as "private"/"public". ...
As it already has been mentioned, there is no way of achieving exactly this goal.
So, that ... makes the myMixin methods available within myModule by just calling mixinMethod1() and have correct scope, and: ... makes the myMixin methods available within myModule by calling module.mixinMethod1() and have correct scope.
And referring to scope ... this is a closed address space created by functions.
Except for closures, scope only is available during a function's runtime
within this function's body. It never ever can be manipulated/spoofed.
The term one is looking for is context. JavaScript, being in many ways highly
dynamic, is build upon late binding (the object/target/context a method is called
on gets evaluated/looked up at runtime) and two kinds of delegation.
Context gets delegated either automatically by "walking the prototype chain"
or explicitly by one of both call methods which every function object does provide
- either call or apply.
Thus JavaScript already at language core level does offer a function based
Mixin pattern that is mightier than any of the available extend(s) or mixin
implementations for it provides delegation for free and is able of passing
around state which almost every of the blamed helpers does lack unless there
was effort of implementing this feature again in a rather roundabout fashion
(or ass-backwards to put it bluntly).
Bergi for his explanation already earned the bounties.
Within his answer's last paragraph there is a link to resources of mine that
already got outdated 3 month after giving the referred talk. Due of not having
enough reputation points, I'm not able to comment his answer directly. For this
I'll take the chance pointing now to the latest state of my personal research and
understanding of »The many talents of JavaScript for generalizing Role Oriented Programming approaches like Traits and Mixins«
Back again answering the OP's question.
I'm going to change the two first given code examples from the assumed module pattern
and the rather exemplarily provided mixin code base towards a plain constructor function
and what I'm meanwhile tempted to call a "proxified" and/or "bicontextual" mixin in order
to boil down the mechanics of delegating two different target/context objects at once.
Thus demonstrating a pure function based mixin pattern that might come closest to what
the OP tries to achieve.
var MyBicontextualMixin = function (localProxy) {
localProxy.proxifiedAccessible = function () {
console.log("proxified accessible.");
};
this.publiclyAccessible = function () {
console.log("publicly accessible.");
};
};
var MyConstructor = function () {
var localProxy = {};
MyBicontextualMixin.call(this, localProxy);
var locallyAccessible = localProxy.proxifiedAccessible;
// call 'em
locallyAccessible(); // "proxified accessible."
this.publiclyAccessible(); // "publicly accessible."
};
(new MyConstructor);
// will log:
//
// proxified accessible.
// publicly accessible.
This special pattern also is the underlying base for composing pure
function based Traits that rely on conflict resolution functionality
provided by "proxified" Mixins that won't expose this functionality
into public.
And for not ending up that theoretical there will be a "real world example",
composing a Queue module out of various reusable mixins that entirely
worship the approach of DRY. It also should answer the OP's question about
how to achieve encapsulation and exposition build only upon the module
pattern and function based mixin composition.
var Enumerable_first_last_item = (function (global) {
var
parseFloat = global.parseFloat,
math_floor = global.Math.floor,
// shared code.
first = function () {
return this[0];
},
last = function () {
return this[this.length - 1];
},
item = function (idx) {
return this[math_floor(parseFloat(idx, 10))];
}
;
return function () { // [Enumerable_first_last_item] Mixin.
var enumerable = this;
enumerable.first = first;
enumerable.last = last;
enumerable.item = item;
};
}(window || this));
var Enumerable_first_last_item_proxified = function (list) {
Enumerable_first_last_item.call(list);
// implementing the proxified / bicontextual [Enumerable_first_last_item] Mixin.
var enumerable = this;
enumerable.first = function () {
return list.first();
};
enumerable.last = function () {
return list.last();
};
enumerable.item = function (idx) {
return list.item(idx);
};
};
var Allocable = (function (Array) {
var
array_from = ((typeof Array.from == "function") && Array.from) || (function (array_prototype_slice) {
return function (listType) {
return array_prototype_slice.call(listType);
};
}(Array.prototype.slice))
;
return function (list) { // proxified / bicontextual [Allocable] Mixin.
var
allocable = this
;
allocable.valueOf = allocable.toArray = function () {
return array_from(list);
};
allocable.toString = function () {
return ("" + list);
};
allocable.size = function () {
return list.length;
};
Enumerable_first_last_item_proxified.call(allocable, list);
};
}(Array));
var Queue = (function () { // [Queue] Module.
var
onEnqueue = function (queue, type) {
//queue.dispatchEvent({type: "enqueue", item: type});
},
onDequeue = function (queue, type) {
//queue.dispatchEvent({type: "dequeue", item: type});
}/*,
onEmpty = function (queue) {
//queue.dispatchEvent({type: "empty"});
}*/,
onEmpty = function (queue) {
//queue.dispatchEvent("empty");
},
Queue = function () { // [Queue] Constructor.
var
queue = this,
list = []
;
queue.enqueue = function (type) {
list.push(type);
onEnqueue(queue, type);
return type;
};
queue.dequeue = function () {
var type = list.shift();
onDequeue(queue, type);
(list.length || onEmpty(queue));
return type;
};
//Observable.call(queue); // applying the [Observable] Mixin.
Allocable.call(queue, list); // applying the bicontextual [Allocable] Mixin.
},
isQueue = function (type) {
return !!(type && (type instanceof Queue));
},
createQueue = function () { // [Queue] Factory.
return (new Queue);
}
;
return { // [Queue] Module.
isQueue : isQueue,
create : createQueue
};
}());
var q = Queue.create();
//q.addEventListener("enqueue", function (evt) {/* ... */});
//q.addEventListener("dequeue", function (evt) {/* ... */});
//q.addEventListener("empty", function (evt) {/* ... */});
console.log("q : ", q); // { .., .., .., }
console.log("q.size() : ", q.size()); // 0
console.log("q.valueOf() : ", q.valueOf()); // []
"the quick brown fox jumped over the lazy dog".split(/\s+/).forEach(function (elm/*, idx, arr*/) {
console.log("q.enqueue(\"" + elm + "\")", q.enqueue(elm));
});
console.log("q.size() : ", q.size()); // 9
console.log("q.toArray() : ", q.toArray()); // [ .., .., .., ]
console.log("q.first() : ", q.first()); // "the"
console.log("q.last() : ", q.last()); // "dog"
console.log("q.item(2) : ", q.item(2)); // "brown"
console.log("q.item(5) : ", q.item(5)); // "over"
console.log("q.dequeue()", q.dequeue()); // "the"
console.log("q.dequeue()", q.dequeue()); // "quick"
console.log("q.dequeue()", q.dequeue()); // "brown"
console.log("q.dequeue()", q.dequeue()); // "fox"
console.log("q.dequeue()", q.dequeue()); // "jumped"
console.log("q.size() : ", q.size()); // 4
console.log("q.toArray() : ", q.toArray()); // [ .., .., .., ]
console.log("q.first() : ", q.first()); // "over"
console.log("q.last() : ", q.last()); // "dog"
console.log("q.item(2) : ", q.item(2)); // "lazy"
console.log("q.item(5) : ", q.item(5)); // undefined
.as-console-wrapper { max-height: 100%!important; top: 0; }

Javascript OOP public and private variable scope

I've got a question regarding public and private variables in a Javascript object. Here's the simple code I've been playing with to get my head around variable scope as well as private and public properties.
var fred = new Object01("Fred");
var global = "Spoon!";
function Object01(oName) {
var myName = oName;
this.myName = "I'm not telling!";
var sub = new subObject("underWorld");
this.sub = new subObject("Sewer!");
Object01.prototype.revealName = function() {
return "OK, OK, my name is: " + myName + ", oh and we say " + global;
}
Object01.prototype.revealSecretName = function() {
console.log ("Private: ");
sub.revealName();
console.log("Public: ");
this.sub.revealName();
}
}
function subObject(oName) {
var myName = oName;
this.myName = "My Secret SubName!";
subObject.prototype.revealName = function() {
console.info("My Property Name is: " + this.myName);
console.info("OK, my real name is: " + myName + ", yeah and we also say: " + global);
}
}
The funny thing I've observed so far is within my objects, a plain var is treated as private (obviously, since they are in a function block), and a this version is public. But I've noticed that the a variable with the same name with this.xxx seems to be considered a different variable. So, in the example above, my object fred will report something different for this.myName compared with my function to pull my var myName.
But this same behavior isn't the same for a sub-object I create. In the case of var sub vs this.sub both above use a new subObject call to supposedly make two subObjects. But it seems both this.sub and var sub return the Sewer! version.
Som I'm a bit confused about why if I use Strings for this.myName and var myName I get two different results, but my attempt to do the same with another object doesn't produce a similar result? I guess it could be that I'm using them wrong, or not understanding the differences between a this and var version.
Your biggest problem here isn't actually the difference between this-based object properties and var-declared variables.
Your problem is that you're trying to make prototype act as a wrapper that will give you protected class properties which are available to sub-classes, let alone instances of your main class.
prototype can not work on "private" members of a class at all (that being the variables defined within the scope of the constructor function, rather than being properties added to the constructed object you're returning).
function Person (personName) {
var scoped_name = personName;
this.name = "Imposter " + scoped_name;
}
Person.prototype.greet = function () { console.log("Hi, I'm " + this.name + "!"); };
var bob = new Person("Bob");
bob.greet(); // "Hi, I'm Imposter Bob!"
The point of the prototype string is either to provide methods which operate on the publicly-accessible properties of your objects (like if you wanted to change the value of this.name, but you'd forever lose the hidden scoped_name reference)...
...or if you want ALL of the same kind of object to have access to the SAME value.
function Student (name, id) {
function showIDCard () { return id; }
function greet () { console.log("I'm " + name + ", and I attend " + this.school); }
this.showID = showIDCard;
this.greet = greet;
}
Student.prototype.school = "The JS Academy of Hard-Knocks";
Student.prototype.comment_on_school = function (feeling) {
console.log("I " + feeling + " " + this.school);
}
var bob = new Student("Bob", 1);
var doug = new Student("Doug", 2);
var mary = new Student("Mary", 1);
mary.school = "The JS School of Closure";
bob.greet(); // I'm Bob and I attend The JS School of Hard-Knocks
mary.greet(); // I'm Mary and I attend the JS School of Closure
mary.comment_on_school("love"); // I love The JS School of Closure
prototype has defined a default value for school, for Students who aren't given their own.
prototype also provided functions which can be shared between objects, because the functions use this to access the actual properties of the object.
Any internal variables of the function can ONLY be accessed by properties or methods which are defined INSIDE of the function.
So in this case, the prototype methods can NEVER access id, except through this.showID, because this.showID is a reference to the showIDCard function, which is created for each and every single student, who has their own unique id, and their own copy of that function has a reference to their own unique copy of that argument.
My suggestion for applying large-scale "class" methodology to JS is to go with a style which favours composition of objects.
If you're going to sub-class, make each sub-class a module, with its own public-facing interface, and its own privately-scoped vars, and then make that module the property of whatever you were trying to make, rather than trying to get chains of inheritance working.
That is way, way too much work in JS, if you're anticipating doing something like inheriting from a base-class, and then extending it 8 or 10 generations.
It will just end in tears, and complaints that JS isn't "OOP" (in the style you'd like it to be).
There's no private or public, there's variables and object properties.
Variables and object properties are different in many more ways than the one of variables having a variable scope and object properties not having a variable scope. Variable scope is not the same as private property of an object, because it's not a property but a variable.
Variables do not belong to any object but they can be sustained through closures. You can invoke those closures as a property of any object or without any object at all and the supposed private properties will work:
function A() {
var private = 0;
this.setPrivate = function( value ) {
private = value;
};
this.getPrivate = function() {
return private;
};
}
var a = new A();
a.getPrivate() //0;
var b = [];
b.fn = a.setPrivate; //The function is fully promiscuous, especially since the data is closed over by it,
//so it doesn't matter at all where or how it's invoked.
b.fn(1);
a.getPrivate(); //1
You are redefining functions in a prototype object every time the constructor is called. The whole point of prototypes is that you only have to create certain function objects just once. You are assigning methods to the prototype object inside a function,
so every time that function is called, the functions are recreated and form new closures that refer to specific state.
I showed above that closures, because they hold state in the closed over variables, don't care about how they are invoked. So when you assign a closure as a property to the prototype, all the instances you have refer to the latest closure assigned, and you are getting its state.
I recommend using the standard way of defining "classes" in JS and not mixing it up with closures:
function A() {
this._private = 1;
}
//Note, this code is outside any function
//The functions assigned to prototype are therefore only defined once.
A.prototype.getPrivate = function() {
return this._private;
};
A.prototype.setPrivate = function( value ) {
this._private = value;
};
var a = new A();
You can find a good tutorial here: https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Details_of_the_Object_Model
Actually, I advocate using a non-standard approach to defining javascript classes. The following coding convention makes code easy to read and understand for anyone with an object-oriented background; it is also very easy to maintain unlike the Method.prototype=function(){}; method which sucks anytime you want to rename a class, add more methods, understand the hierarchy of a class or even re-interpret what your own code is doing.
Instead, you can declare object-oriented structures using the following architecture:
/**
* public class Animal
**/
(function(namespace) {
var __class__ = 'Animal';
/**
* private static:
**/
var animalCount = 0;
/**
* public Animal(string name)
**/
var constructor = function(name) {
// here you can assert arguments are correct
if(arguments.length == 0) {
return global.error('needs a name');
}
/**
* private:
**/
var animalIndex = animalCount++;
/**
* public:
**/
var operator = {
speak: function() {
console.log('?');
},
getName: function() {
return name;
},
getAnimalIndex: function() {
return animalIndex;
},
};
return operator;
};
/**
* public static Animal()
**/
var global = namespace[__class__] = function() {
// new Animal();
if(this !== namespace) {
// construct a new instance of this class
instance = constructor.apply(this, arguments);
return instance;
}
// Animal();
else {
// return the last instantiation of this class
return instance; // or do whatever you want
}
};
/**
* public static:
**/
// overrides the default toString method to describe this class from a static context
global.toString = function() {
return __class__+'()';
};
// prints a message to the console's error log
global.error = function() {
var args = Array.prototype.slice.apply(arguments);
args.unshift(__class__+':');
console.error.apply(console, args);
};
})(window);
/**
* publc class Dog extends Animal
**/
(function(namespace) {
var __class__ = 'Dog';
/**
* private static:
**/
var dogCount = 0;
/**
* public Dog()
**/
var construct = function(name) {
/**
* private:
**/
var dogIndex = dogCount++;
/**
* public operator() ();
**/
var operator = new Animal(name);
/**
* public:
**/
// overrides parent method 'speak'
operator.speak = function() {
console.log(operator.getName()+': bark!');
};
// method returns value of private variable
operator.getSpeciesIndex = function() {
return dogIndex;
};
return operator;
};
/**
* public static Dog()
**/
var global = namespace[__class__] = function() {
// new Dog();
if(this !== namespace) {
// construct a new instance of this class
instance = construct.apply(this, arguments);
return instance;
}
// Dog();
else {
// return the last instantiation of this class
return instance; // or do whatever you want
}
};
})(window);
/**
* publc class Cat extends Animal
**/
(function(namespace) {
var __class__ = 'Cat';
/**
* private static:
**/
var catCount = 0;
/**
* public Cat()
**/
var construct = function(name) {
// here you can assert arguments are correct
if(arguments.length == 0) {
return global.error('needs a name');
}
/**
* private:
**/
var catIndex = catCount++;
/**
* public operator() ();
**/
var operator = new Animal(name);
/**
* public:
**/
// overrides parent method 'speak'
operator.speak = function() {
console.log(name+': meow!');
};
// method returns value of private variable
operator.getSpeciesIndex = function() {
return catIndex;
};
return operator;
};
/**
* public static Cat()
**/
var global = namespace[__class__] = function() {
// new Cat();
if(this !== namespace) {
// construct a new instance of this class
instance = construct.apply(this, arguments);
return instance;
}
// Cat();
else {
// return the last instantiation of this class
return instance; // or do whatever you want
}
};
})(window);
Now with the above classes declared: Animal, Dog extends Animal, and Cat extends Animal...
We get the following:
new Dog(); // prints: "Animal: needs a name" to error output
var buddy = new Dog('Buddy');
buddy.speak(); // prints: "Buddy: bark!"
var kitty = new Cat('Kitty');
kitty.speak(); // prints: "Kitty: meow!"
var oliver = new Dog('Oliver');
oliver.speak(); // prints: "Oliver: bark!"
buddy.getSpeciesIndex(); // returns 0;
buddy.getAnimalIndex(); // returns 0;
kitty.getSpeciesIndex(); // returns 0;
kitty.getAnimalIndex(); // returns 1;
oliver.getSpeciesIndex(); // returns 1;
oliver.getAnimalIndex(); // returns 2;
I provide this javascript coding convention solely as a means to maintain organized object-oriented structures. I do not boast the performance of such coding style over other conventions, but if you want performance from your code I strongly suggest using Google's Closure Compiler which will optimize the same.
I have derived this javascript coding style from many years of coding experience on my own and the assimilation of critiquing other's code. I swear by it's robustness and modularity and welcome any comments regarding otherwise.
You goofed. Constructors should not change the prototype. Either:
function subObject(oName)
{
var myName = oName;
this.myName = "My Secret SubName!";
}
subObject.prototype.revealName = function()
{
console.info("My Property Name is: " + this.myName);
console.info("OK, my real name is: " + myName + ", yeah and we also say: " + global);
}
Or:
function subObject(oName)
{
var myName = oName;
this.myName = "My Secret SubName!";
subObject.revealName = function()
{
console.info("My Property Name is: " + this.myName);
console.info("OK, my real name is: " + myName + ", yeah and we also say: " + global);
}
}
Blake's answer inspired me, but I found it not doing everything that I wanted, so I hacked away at it until I have something that covers most of the OOP features of C++ in a simple and elegant syntax.
The only things not supported at the moment (but it's a matter of implementing them):
multiple inheritance
pure virtual functions
friend classes
See the github repo for examples and a serious readme:
https://github.com/najamelan/TidBits_Javascript_OoJs

Categories

Resources