I am trying to understand how "classes" work in ES5 and how I can apply my knowledge of traditional, typed object oriented languages like Java to javascript.
In the following code sample I have commented with my questions.
var MyClass = (function () {
// [What am I?] A private variable?
var myVariable1
// Constructor.
function MyClass() {
// Essentially a public variable.
this.myVariable2 = 0;
}
// Public method returning myVariable1.
MyClass.prototype.myMethod1 = function () {
return myVariable1;
};
// Public method returning public variable.
MyClass.prototype.myMethod2 = function () {
return this.myVariable2;
};
// [What am I?] A private method?
function myMethod3 () {
return 0;
}
return MyClass;
}());
I am mostly wondering about the "private" stuff. Like, what happens if I have multiple instances of this class? Can they interfere with each others private variables and functions?
First I'll address this bit:
...and how I can apply my knowledge of traditional, typed object oriented languages like Java to javascript.
You can frequently get away with thinking of JavaScript as being a bit like Java/C#/etc., but if you do:
It'll bite you at some point, because JavaScript is not like Java/C#/etc., it is fundamentally different even though it has some trappings that make it look similar;
and
You'll miss out on the true power of JavaScript by not knowing how to use its fundamentally-different nature.
How do I know? I did exactly that, came from a Java (and even C++) background and assumed JavaScript was similar, and got bitten, and missed out (initially). :-)
That's not remotely meant as any form of criticism, it's just a word to the wise. Try to learn in depth how JavaScript prototypical inheritance and closures work, and you'll find that the way you solve problems will be slightly different than the way you would in Java/C#/etc.
In Old Environments
Answers to your direct queries inline in this code block, but in 2022 I added a bit below ("In Modern Environments") to address the new modern features recently added to JavaScript to directly address these use cases in different ways.
var MyClass = (function () {
// [What am I?] A private variable?
// ==> A private *class* variable (static variable). Not instance-specific.
var myVariable1
// Constructor.
function MyClass() {
// Essentially a public variable.
// ==> A public field/property/variable, choose your terminology. :-)
// ==> The Java spec calls them both fields and variables (oddly).
// ==> In JavaScript, they're called properties.
this.myVariable2 = 0;
}
// Public method returning myVariable1.
// ==> Correct, but note that myVariable1 is shared across all instances
MyClass.prototype.myMethod1 = function () {
return myVariable1;
};
// Public method returning public variable.
// ==> Yes, note that this one is returning an instance-specific field/property/variable
MyClass.prototype.myMethod2 = function () {
return this.myVariable2;
};
// [What am I?] A private method?
// ==> A private *class* method (static method), yes.
function myMethod3 () {
return 0;
}
return MyClass;
}());
I am mostly wondering about the "private" stuff. Like, what happens if I have multiple instances of this class? Can they interfere with each others private variables and functions?
Yes, as I mentioned in the comments, they're class-wide. If you wanted to have a private "instance field", you'd have to declare it within your constructor, and create any functions that needed to have access to it within the constructor so that they closed over it:
function MyClass(arg) {
var privateInstanceInfo = arg; // We could also just use arg directly
this.accessThePrivateInstanceInfo = function() {
return privateInstanceInfo * 42;
};
}
MyClass.prototype.useOnlyPublicInfo = function() {
// This cannot access `privateInstanceInfo` directly.
// It *can* access the function `accessThePrivateInstanceInfo`
// because that's public:
return accessThePrivateInstanceInfo();
};
var c = new MyClass(2);
console.log(c.useOnlyPublicInfo()); // 84
This is all down to a concept called closures, which is outlined in detail in this question and its answers: How do JavaScript closures work? I'll also reference my article from several years ago Closures are not complicated, which while it uses some older terms for things compared to the latest specification, still describes the concepts just fine.
The inline-invoked function (IIFE) you've used as a wrapper creates a single execution context that all of the functions within it close over. That means they have live access to the variables and functions defined within that context, even after the function returns. Since you only call it once, there's only one context, and so only one myVariable1 and myMethod3.
In my example creating private instance information, we use the fact that a new context is created for each call to the constructor. That context isn't shared with anything else, and so becomes instance-specific.
There's a way to get near-private instance properties without having to define functions in the constructor, which is to use a randomly-selected name:
function makeRandomName() {
var str = "";
while (str.length < 10) {
str += String.fromCharCode(32 + Math.floor(95 * Math.random()));
}
return "__" + str;
}
var MyClass = (function() {
var pseudoPrivatePropName = makeRandomName();
function MyClass() {
this[pseudoPrivatePropName] = 42;
}
// ....
return MyClass;
})();
The code inside the IIFE knows the name of the property, the code outside of it doesn't. Now, malicious code could still find the property, but it's become much more challenging, particularly if you have more than one. (And if you have more than one, you need a better name allocator than the one above.) (Details in this very-outdated article in my blog.)
In ES2015 (ES6) you could use
var pseudoPrivatePropName = Symbol();
...instead of having a name allocator, but it doesn't make the property any more private.
In Modern Environments
In modern environments though, you can use new features that have been added to JavaScript for the ES2022 specification:
Class Public Instance Fields & Private Instance Fields
Private instance methods and accessors
Static class fields and private static methods
Here's how you might right MyClass using those features and ES2015's class syntax:
class MyClass {
// Static class field (class-wide, not instance-specific)
static myVariable1;
// Instance class field (property) (instance-specific)
myVariable2 = 0;
// Private class field (instance-specific)
#privateInstanceInfo;
// Private static class field (class-wide, not instance-specific)
static #privateStaticInfo;
// Constructor for the class
constructor(arg) {
this.#privateInstanceInfo = arg;
}
// Public instance method returning static member
myMethod1() {
// Note that `MyClass.myVariable1` is shared across all instances
return MyClass.myVariable1;
}
// Public instance method return instance field (property) value
myMethod2() {
return this.myVariable2;
}
// Public instance method accessing the private field; all methods declared
// for the class can access it, not just this one
accessThePrivateInstanceInfo() {
return this.#privateInstanceInfo * 42;
}
// Private instance method
#myMethod3() {
return 0;
}
// Static method
static myStaticMethod() {
return this.#getPrivateStaticInfo(); // Or `MyClass.#getPrivateStaticInfo();`
}
// Private static method
static #getPrivateStaticInfo() {
return this.#privateStaticInfo; // Or `MyClass.#privateStaticInfo`
}
}
On those last two, the static method and the private static method, note that usually this during the call will refer to the class constructor itself (MyClass), because usually you're calling static members by doing MyClass.myStaticMethod(). But as usual with this, that's not necessarily true; if you did const f = MyClass.myStaticMethod; f();, this during the call wouldn't refer to MyClass. Using this in static methods to refer to the constructor is friendly to subclasses (because a subclass constructor's prototype is its superclass constructor; details here), but does mean you have to deal with the usual caveats around this.
Use # for private, and _ for protected.
Related
I have been working with JS for a few months now and I stumbled upon this interesting (at least to me) thing.
Take a look at this code:
class myClass
{
constructor()
{
this.x = 0;
}
}
function myFunc(){}
myClass.myFunc = myFunc;
I can call myClass.myFunc(), but myClass is just a function. In fact, I could rewrite it as
function myClass()
{
this.x = 0;
}
and it would behave the same and I would still be able to call myClass.myFunc(). So what actually is a function (like, "under the hood")? It seems to behave more like an object that can be called if it makes any sense, thus being able to have fields of its own.
Also, is this considered bad practice?
In node I have
module.exports = myClass;
module.exports.myFunc = myFunc;
Is this okay to do? Or is this frowned upon? What are the cons, if any?
EDIT: I'm not asking how to have a static method, I'm asking why this happens.
In JavaScript a function is an actual value. Values a categorized by data type (a data type describes a possible set of values). JavaScript has the following data types:
Boolean
Number
String
Undefined
Null
Symbol
Object
A function is obviously neither of the first 6, it is indeed an Object. And as such it can have arbitrary properties, just like any other object.
What makes a function object special?
Per specification objects have "internal methods". You can think of them as being just like normal properties except that they cannot be accessed in user code. Only the JavaScript engine can access them.
Function objects have an internal method called [[Call]] and an internal slot called [[ECMAScriptCode]]. The latter contains a parsed representation of the function body and is evaluated when [[Call]] is invoked (which happens in a call expression (foo())).
Specifically for classes, or rather the functions created through class syntax, there is also the internal [[Construct]] method. It works very similar to [[Call]] but is used when a function is invoked via the new keyword.
See also
What is the main core difference between a javascript function and javascript object?
If functions are objects, where does the function's body go? (referring to an earlier version of the spec)
Why the property "prototype" is absent in definition methods of ES6 classes
You can use static method:
class myClass
{
constructor()
{
this.x = 0;
}
static myFunc(){
return 'Hello';
}
}
module.exports = myClass
or simply export a new instance of myClass:
class myClass
{
constructor()
{
this.x = 0;
}
myFunc(){
return 'Hello';
}
}
module.exports = new myClass
In both approach you can treat myFunc as a static function:
const myclass = require('myClass');
myClass.myFunc();
// will print out 'Hello'
I am learning JS these days and I am unable to assimilate this Functional Pattern on page 52 of the book.
Functional
One weakness of the inheritance patterns we have seen so far is that we get no privacy.
All properties of an object are visible. We get no private variables and no
private methods. Sometimes that doesn’t matter, but sometimes it matters a lot. In frustration, some uninformed programmers have adopted a pattern of pretend
privacy. If they have a property that they wish to make private, they give it an odd looking name, with the hope that other users of the code will pretend that they cannot
see the odd looking members. Fortunately, we have a much better alternative in
an application of the module pattern.
We start by making a function that will produce objects. We will give it a name that
starts with a lowercase letter because it will not require the use of the new prefix. The
function contains four steps:
It creates a new object. There are lots of ways to make an object. It can make an
object literal, or it can call a constructor function with the new prefix, or it can
use the Object.beget method to make a new instance from an existing object, or
it can call any function that returns an object.
It optionally defines private instance variables and methods. These are just ordinary
vars of the function.
It augments that new object with methods. Those methods will have privileged
access to the parameters and the vars defined in the second step.
It returns that new object.
Here is a pseudocode template for a functional constructor (boldface text added for
emphasis):
var constructor = function (spec, my) {
var that, //other private instance variables;
my = my || {};
// Add shared variables and functions to my
that = a new object;
// Add privileged methods to that
return that;
}
The spec object contains all of the information that the constructor needs to make an
instance. The contents of the spec could be copied into private variables or transformed
by other functions. Or the methods can access information from spec as they
need it. (A simplification is to replace spec with a single value. This is useful when
the object being constructed does not need a whole spec object.)
Can anyone explain, what's going on there (in layman terms) and where such a pattern is useful?
Note: While the book you refer to is indeed an immensely helpful book, its quite ancient. Some of the "good" (and even "bad") parts have been replaced by even better alternatives and features in newest versions of JavaScript.
One weakness of the inheritance patterns we have seen so far is that
we get no privacy. All properties of an object are visible. We get no
private variables and no private methods.
A Javascript object has "properties", which can be other objects, or functions. Consider:
var obj = {a: 1, do: function(){console.log('done');} }
Nothing is stopping you from calling obj.a = 5, or obj.done().
But one might counter that that's not a good way of creating objects. We better have a prototype or class from which we can create new instances:
function Animal(name) {
this._name = name;
}
Animal.prototype.print = function(){console.log(this._name)};
or in more recent JavaScript versions:
class Animal {
constructor(name){
this._name = name;
}
print(){
console.log(this._name);
}
}
In frustration, some uninformed programmers have adopted a pattern of
pretend privacy. If they have a property that they wish to make
private, they give it an odd looking name, with the hope that other
users of the code will pretend that they cannot see the odd looking
members.
This is a comment on above code. When declaring JavaScript classes or functions, there is no official, standard, "fool proof AND syntactically elegant" way of keeping instance variables private. That is, an easy, clean way of declaring a variable that is only accessible to methods defined in that class or prototype (See this answer). So, people follow some agreed upon patterns, one of which is prefixing the variables names with a _. This actually provides no privacy to internal variables of a class instance.
With advent of the module system, one could write JavaScript code in a separate file/container and choose to make only specific objects visible to the outside world. A CommonJS example:
Animal.js:
const props = new WeakMap();
class Animal {
constructor(name){
props.set(this,{});
props.get(this).name = name;
}
set age(n){
props.get(this).age = age;
}
function print(){
console.log(props.get(this));
}
}
module.exports = Animal;
Above is one of the ways to declare a class with private properties not accessible from outside unless intentionally leaked. Notice how the object props is not exported to outside world.
Fortunately, we have a much better alternative in an application of
the module pattern.
You might think that the above module code is actually what this text means, but the above implementation is a newer version using latest features. The old school way the points in text illustrate is to expose an object creator (a.k.a factory) function. Everything declared inside the creator function and outside the created object is private by design:
function createAnimal(name){
var age = 0;
var animal = {};
animal.setAge = function(a){age = a;};
animal.getName = function(){return name;};
animal.print = function(){console.log({'name':name,'age':age});};
}
Inheritance here is a call to super creator and modifying the super instance:
function createDog(name, color){
var breed = 'unknown';
var dog = createAnimal(name);
dog.setBreed = function(b){breed = b;};
}
Essentially, the idea is to hide private variables within a closure. The variables being closed over are the (not shown) "other private instance variables", and the methods that actually are closing over these variables are the (also not shown) "privileged methods".
For example, take this function:
var createBoard = function (rows, cols) {
var cells = [];
var board = {};
for (var i = 0; i < rows; i++) {
cells[i] = [];
for (var j = 0; j < cols; j++) {
cells[i][j] = { player: null };
}
}
board.play = function (row, col, player) {
if (cells[row][col].player === null) {
cells[row][col].player = player;
}
};
board.getPlayer = function (row, col) {
return cells[row][col].player;
};
return board;
};
And let's assume we call this function to create an 8x8 gameboard:
var board = createBoard(8,8);
board.play(1,2,"Player1");
console.log(board.getPlayer(1,2));
board.play(1,2,"Player2"); // Doesn't actually do anything
// Note this code has no direct access to cells[][] except via the two
// methods we defined on the board object.
In this case, we return a board object. The board internally has access to a cells array, but we don't let anyone modify this except using our two methods, play (which occupies a board space only if it was previously unoccupied) and a getPlayer method that returns the player at a given space. Cells[][] is totally hidden to the user of this code - they couldn't cheat by changing our cell array directly.
JavaScript is an object-based language based on prototypes, rather than being class-based. 1
Compare that with Object-Oriented languages based on classes like PHP, Java, etc. In those languages, a class can be defined and member variables can have various visibility inside and outside the class. For instance, PHP has visibility set on three levels: public, protected or private.
Class members declared public can be accessed everywhere. Members declared protected can be accessed only within the class itself and by inherited classes. Members declared as private may only be accessed by the class that defines the member.2
class MyClass {
public $public = 'Public';
protected $protected = 'Protected';
private $private = 'Private';
function printHello() {
echo $this->public;
echo $this->protected;
echo $this->private;
}
}
$obj = new MyClass();
echo $obj->public; // Works
echo $obj->protected; // Fatal Error
echo $obj->private; // Fatal Error
But in JavaScript, we don't really have such a concept of private variables (in the same sense). That is what the author is talking about when describing the module pattern.
So if we wanted to make an analagous construct in Javascript, we could make something like this:
var MyClass = function (rows, cols) {
//this could be used in prototype functions
var private = 'Private';
var members = {
public: 'Public';
getHello: function() {
return 'MyClass _ ' + private;
}
};
return members;
};
If I understand correctly, according to Douglas Crockford http://javascript.crockford.com/private.html, the "privileged" methods are similar to what we know as "public" methods. and "public" methods are something that's a bit different.
Here's how I understand it:
"Privileged" methods can access private variables since it is defined inside the closure when the rest of the private variables were defined.
var C = function(){
var private;
this.privilegedMethod = function(){
/* blah blah */
};
}
var cObj = new C();
"Public" methods are the ones that are added to the object outside of the object itself, through prototype.
var C = function(){
/* blah blah */
}
C.prototype.publicMethod = function(){
/* blah blah */
};
var cObj = new C();
I find these definitions of "privileged" and "public" very confusing. I think the "privileged" method is nothing more than actually a public method as we know it from object oriented programming. And I think the "public" method is the one that should be named as something else. If you think about it, it's a weird type of function, it's a member of the object but it cannot access any other private variables, which means it doesn't contribute to encapsulation. It's almost like an independent helper method for the object.
So I was wondering, why did Douglas Crockford come up with these confusing terms? And why have the javascript community adopted these terminologies? Or if I'm wrong about something, please correct me.
Since there are no scope modifiers like public/private/protected in JavaScript, in order to come close to the OOP world, Douglas Crockford is using such names, not to confuse anyone coming from, lets say Java
The privileged method can see variables, defined inside the function (An important note here - in JavaScript, the only scope is function scope. There's no block scope) so they are "privileged". Yes, they can be called from an object instance, but the important thing here is, that they see all the stuff, declared with var (the real private stuff)
On the other hand, public methods, that are attached to the prototype of the object have one more important thing - they are evaluated once and seen for all instances of the given object.
If you use the this keyword inside a prototype method, it will point to the current instance of the Object but you will be able to see only things, that are defined within this.
I don't know if it gets clear, but the main thing here is that JavaScript is prototype based language and the prototype chain was introduced in the language in order to make inheritence possible.
Vlad, I agree with you : I am confused too!
Look here (from http://javascript.crockford.com/private.html):
function Container(param) {
// methode privee
function dec() {
console.log('private method is looking for private member secret : ' + secret);
if (secret > 0) {
secret -= 1;
return true;
} else {
return false;
}
}
// membres privées
var secret = 3;
var that = this;
// méthode privilégiée
this.service = function () {
console.log('priviligied method is looking for private member secret : ' + secret);
return dec() ? that.member : null;
};
// membres publiques
this.member = param;
}
var myContainer = new Container('abc');
Container.prototype.stamp = function (string) {
console.log('public method is looking for private member secret : ' + this.secret);
return this.member + string;
}
console.log(myContainer.stamp('def'));
//for (i=0;i<4;i++)
console.log(myContainer.service());
priviliged vs public
This jsfiddle sample will display :
public method is looking for private member secret : undefined
abcdef
priviligied method is looking for private member secret : 3
private method is looking for private member secret : 3
abc
So, the answer : public methods <=> priviliged methods isn't it?
In a traditional OOP language, all of the members of a class have access to all of the other members of a class.
This is not the case in Javascript. A public method may have access to private data that none of the other members of the class (viz. constructor function) know about. Equally, other members of the class may have data that the method cannot see.
Consider below:
function TheirTrait() {
var privateData = "foo";
this.privilegedMethod = function() {
return privateData;
}
}
function MyClass() {
var privateData = undefined;
this.publicMethod = function() {
return privateData;
}
TheirTrait.apply(this, arguments);
}
var myObject = new MyClass();
myObject.privilegedMethod() // returns "foo"
myObject.publicMethod() // returns undefined
As you can see, both publicMethod and privilegedMethod are public in the sense that they can both be accessed externally, but privilegedMethod has access to additional data.
The key difference between both kind of methods is that Privileged Methods CAN WE INHERIT, this means that child classes can access them directly, but Public Methods are not available for child classes, of course in a classical inheritance approach.
Hope this be useful.
Privileged methods are created using "this" keyword and public methods are created using prototype property of the constructor function.
Privileged methods can access private variables and methods. Public methods can call privileged methods but not private methods.
Both privileged and public methods available within and outside the object.
I'm building a system, with similar details as this question: Can I have different copies of a static variable for each different type of inheriting class
Except it's in JavaScript!
I'm going to have a set of subclasses. Each subclass will have a lot of instances created of it during the life of the program. Each instance of a particular subclass will have different values, except for a file that is common to all. I don't want each instance to have a copy. I want it static (one copy for all). Each different subclass uses a different file though. I want each subclass to inherit the FACT that it HAS a file from a superclass.
EDIT: Quick Summary:
goal: create a class that is a constructor that
constructs the definition of a
subclass, allowing a variable:
- Appearing in every subclass
- Unique to a particular subclass
- Shared by all instances of a particular subclass (one copy for all)
Attempt at illustrating this in code:
var instance1ofSubclass1 = {
staticVar:"SAMEVAL_1", // For brevity I'm showing how staticVar is
// the same. It's notsupposed to be public.
uniqueVar:"adsfasdf"
};
var instance2ofSubclass1 = {
staticVar:"SAMEVAL_1",
uniqueVar:"zxbvczbxc"
};
var instance3ofSubclass1 = {
staticVar:"SAMEVAL_1",
uniqueVar:"qwrtytry"
};
var instance1ofSubclass2 = {
staticVar:"SAMEVAL_2", //<--notice the static var is different
// between subclasses
uniqueVar:"oipoiuu"
};
var instance2ofSubclass2 = {
staticVar:"SAMEVAL_2",
uniqueVar:"hljkhlj"
};
var instance3ofSubclass2 = {
staticVar:"SAMEVAL_2",
uniqueVar:"bnmbmbmnm"
};
My class definitions could go like this:
var subclass1 = (function () {
var staticVar = "SAMEVAL_1"
return function (unique) {
return {
uniqueVar:unique
};
};
}());
var subclass2 = (function () {
var staticVar = "SAMEVAL_2" //<-- different static variable
return function (unique) {
return {
uniqueVar:unique
};
};
}());
Now, I want to go a step further and make a superclass for these classes. That's where I'm stuck. I don't want to have a staticVar definition in every subclass. I want to get it from the superclass.
First of, the compiler will never be able to prevent you from forgetting something since there is no compiler. That's something we'll have to live without.
My suggestion for you would be to use prototyping for this. If the prototype of the superclass contains your variable, the same instance will be used for all the subclasses. And you wont have to repeat yourself in your subclass-files. Static and inherited, so to speak.
MySuperClass.prototype.myStaticVar = "giantFile";
The downside of this solution is that the variable won't really be private. On the other hand, do you really, really need it to be private?
The concept of privacy is a little funny anyhow. In C/C++ everything (private stuff too) can be accessed by pointer-magic. In C# you can use reflection to alter private variables. Nothing is ever really private. JavaScript is even funnier since the scripts in the browser can be altered by the end-user himself! In my opinion, hiding in plain sight is the way to go in this case. Name your variable appropriately (for example, add an underscore or two the beginning of it's name to signify "privacy").
if i'm reading this right, I had a similar issue that you did. Check this SO question that i posted a few weeks ago.
to take that a step further, my .add() method checks to see if the passed in namespace has a supr object attached to it, if not, then it appends the base object called supr to that namespace so that it can have easy access to the root.
I think I've figured it out.
Fiddle: http://jsfiddle.net/zXMaM/
The pattern I've created sends a class definition through another function (essentially the super class) that creates an additional closure for the necessary private static variables and at the same time augments the object created by the class passed in to access the private static variables.
It's hard to explain as this is new to me too, but hopefully between the code and my comments it is followable.
The "superclass" method:
var superClass = function (yourPrivateStaticVar, classDef) {
var privateStatic = yourPrivateStaticVar;
return function () { // return a new constructor (only invoked when a new
// instance is created!)
// run the constructor, grab the object it creates
var newObj = classDef();
// now, augment the object created (these vars/methods have no
// knowledge of the subclass!)
//add private vars/methods to the object
function getPrivStatic() {
return privateStatic;
}
var example_inherited_private_var;
//add public vars/methods to the object
newObj.getPrSt_directly = function () {
return privateStatic;
}
newObj.getPrSt_throughPrivateFunc = function () {
return getPrivStatic();
}
newObj.example_inherited_public_var = "something";
//return the augmented object (a new *instance* of the subclass)
return newObj;
};
};
Defining a "subclass":
//pass the definition of subclass1 through the superclass method and get it back
var subClass1 = superClass("yourChosenPrivateStaticValue", function () {
//private variables/methods go here
return { //this is the actual instance object
//public variables/methods go here
};
});
Again, the fiddle: http://jsfiddle.net/zXMaM/
Let me explain, this is about displaying class source code in IDEs. I have always only one class per file. A class is declared like this in the file mod1.js:
MYGLOB.MOD1.ClassXy = function () {
//constructor, do somothing
}
MYGLOB.MOD1.ClassXy.prototype.memberfunc1 = function () {
//member function 1, do somothing
}
(There are many more functions like memberfunc1 in the real class.)
But in different IDEs and editors the width of the function list is now very large. I want the function lists to display only the last part of the function name (the function name itself).
How about this:
ClassXy = function () {
//constructor, do somothing
}
memberfunc1 = function () {
//member function 1, do somothing
}
MYGLOB.MOD1.ClassXy = ClassXy;
MYGLOB.MOD1.ClassXy.prototype.memberfunc1 = memberfunc1;
It displays nice in the function list. It does not disturb that there are the 2 long assignments at the bottom of the file. But I have the global namespace polluted. How to do this without affecting the global namespace with the global "ClassXy" and "memberfunc1"? (MYGLOB.MOD1.ClassXy is fine.)
Can I do this with parens / closures somehow or what do you suggest? And keep the effect of having the clean function list in the IDE, at least the first part of the function list showing me the member function with their short names?
Please don't suggest different IDEs or editors, this is not about choosing a different code editor, please open a different question on your own if you want to discuss that. This question is about javascript and classes.
Maybe this is a simple thing, but I am quite new to javascript.
It will depend a bit on the capabilities of the editors you're using, but the module pattern can be useful for this (and for avoiding global namespace pollution in general). I'll start the answer assuming you're doing this when defining your classes (objects, really), but there's a note at the end about using shorthand aliases when consuming classes (objects) as well.
Basic example of module pattern
var MYGLOB.MOD1.ClassXy = (function() {
// Define your constructor function
function ClassXy() {
}
// Define your member functions
function memberfunc1() {
}
// Put your member functions on the prototype
ClassXy.prototype = {
memberfunc1: memberfunc1
};
// Return the constructor function to assign it to the MYGLOB.MOD1 object
return ClassXy;
})();
There I replaced the prototype; you may want to just add to it instead, in which case I suggest having a utility function somewhere that does a shallow property copy:
function shallowCopy(dest, src) {
var name;
for (name in src) {
// Depending on your needs, you may want to check
// src.hasOwnProperty(name) here and only copy it
// when that's true
dest[name] = src[name];
}
}
And then replacing the assignment to prototype above with this:
shallowCopy(ClassXy.prototype, {
memberfunc1: memberfunc1
});
Named functions
Amongst other things, using this pattern means you're using named functions rather than anonymous ones. That helps your tools (debuggers in particular) help you. This format creates an anonymous function and assigns it to a property on an object:
MyObject.functionName = function() { ... }; // Not ideal
Whereas if you use the module pattern, you can declare your functions normally and then assign them to properties later (see above); that way they have names that debuggers can show you in call stacks, etc.
Private utility functions
The pattern also provides a nice way of having utility functions (or class-wide data) used by the class without having to make them public at all -- not on the constructor function, not on its prototype, not on instances. For instance, here's the above with a private utility function:
var MYGLOB.MOD1.ClassXy = (function() {
// Define your constructor function
function ClassXy() {
}
// Define your member functions
function memberfunc1() {
// Call our utility function. In this form, be aware that
// within the utility, `this` will *not* be set within
// the utility
utility('bar');
// Alternate form if you want to call `utility` as though it
// were an instance member function; within the utility, it
// can refer to `this` and have it mean the same thing it
// means here in `memberfunc1`
utility.call(this, 'bar');
}
// A utility function. This is entirely private to the class,
// we don't make it a property of anything and so it's never
// visible outside the closure
function utility(foo) {
alert("foo = " + foo);
}
// Put your member functions on the prototype
shallowCopy(ClassXy.prototype, {
memberfunc1: memberfunc1
});
// Return the constructor function to assign it to the MYGLOB.MOD1 object
return ClassXy;
})();
Using a helper
The above may seem a bit clunky at first, but there's no reason you can't create helpers to make it easier to define classes this way. That's what I've done; using my helper I'd define your example like this:
MYGLOB.MOD1.ClassXy = Class.defineClass(function() {
// Takes the place of the constructor function; defining it is
// optional, though, if you don't need to do anything when created
function initialize() {
}
// A member function
function memberfunc1() {
}
// Export our public symbols
return {
initialize: initialize,
memberfunc1: memberfunc1
};
});
You can grab the helper (and the reasoning behind it) from my blog post on the topic.
Consuming long-winded APIs
This same pattern can also be turned on its head, when you want to consume an API that's long-winded: Just define a function, pass in the long-winded things as arguments, and use the argument name instead:
(function(xy) {
// Use the member function; within this closure, xy = MYGLOB.MOD1.ClassXy
xy.memberfunc1();
})(MYGLOB.MOD1.ClassXy);
You can always use an object as a name space. For example, you create an object with short variable name and use it to hold your function. Once ready, you can assign it to your actual production class name.
Fs = new Object();
Fs['ClassXy'] = function() {
this.time = new Date();
alert("From ClassXy: " + this.time);
};
Fs['memberfunc1'] = function() {
alert("From memberfunc1: " + this.time);
};
ClassXy = Fs['ClassXy'];
ClassXy.prototype.memberfunc1 = Fs['memberfunc1'];
const aCX1 = new ClassXy();
aCX1.memberfunc1();
The example code above works.
Hope this helps.