JavaScript OOP in NodeJS: how? - javascript

I am used to the classical OOP as in Java.
What are the best practices to do OOP in JavaScript using NodeJS?
Each Class is a file with module.export?
How to create Classes?
this.Class = function() {
//constructor?
var privateField = ""
this.publicField = ""
var privateMethod = function() {}
this.publicMethod = function() {}
}
vs. (I am not even sure it is correct)
this.Class = {
privateField: ""
, privateMethod: function() {}
, return {
publicField: ""
publicMethod: function() {}
}
}
vs.
this.Class = function() {}
this.Class.prototype.method = function(){}
...
How would inheritance work?
Are there specific modules for implementing OOP in NodeJS?
I am finding a thousand different ways to create things that resemble OOP.. but I have no clue what is the most used/practical/clean way.
Bonus question: what is the suggested "OOP style" to use with MongooseJS? (can a MongooseJS document be seen as a Class and a model used as an instance?)
EDIT
here is an example in JsFiddle please provide feedback.
//http://javascriptissexy.com/oop-in-javascript-what-you-need-to-know/
function inheritPrototype(childObject, parentObject) {
var copyOfParent = Object.create(parentObject.prototype)
copyOfParent.constructor = childObject
childObject.prototype = copyOfParent
}
//example
function Canvas (id) {
this.id = id
this.shapes = {} //instead of array?
console.log("Canvas constructor called "+id)
}
Canvas.prototype = {
constructor: Canvas
, getId: function() {
return this.id
}
, getShape: function(shapeId) {
return this.shapes[shapeId]
}
, getShapes: function() {
return this.shapes
}
, addShape: function (shape) {
this.shapes[shape.getId()] = shape
}
, removeShape: function (shapeId) {
var shape = this.shapes[shapeId]
if (shape)
delete this.shapes[shapeId]
return shape
}
}
function Shape(id) {
this.id = id
this.size = { width: 0, height: 0 }
console.log("Shape constructor called "+id)
}
Shape.prototype = {
constructor: Shape
, getId: function() {
return this.id
}
, getSize: function() {
return this.size
}
, setSize: function (size) {
this.size = size
}
}
//inheritance
function Square(id, otherSuff) {
Shape.call(this, id) //same as Shape.prototype.constructor.apply( this, arguments ); ?
this.stuff = otherSuff
console.log("Square constructor called "+id)
}
inheritPrototype(Square, Shape)
Square.prototype.getSize = function() { //override
return this.size.width
}
function ComplexShape(id) {
Shape.call(this, id)
this.frame = null
console.log("ComplexShape constructor called "+id)
}
inheritPrototype(ComplexShape, Shape)
ComplexShape.prototype.getFrame = function() {
return this.frame
}
ComplexShape.prototype.setFrame = function(frame) {
this.frame = frame
}
function Frame(id) {
this.id = id
this.length = 0
}
Frame.prototype = {
constructor: Frame
, getId: function() {
return this.id
}
, getLength: function() {
return this.length
}
, setLength: function (length) {
this.length = length
}
}
/////run
var aCanvas = new Canvas("c1")
var anotherCanvas = new Canvas("c2")
console.log("aCanvas: "+ aCanvas.getId())
var aSquare = new Square("s1", {})
aSquare.setSize({ width: 100, height: 100})
console.log("square overridden size: "+aSquare.getSize())
var aComplexShape = new ComplexShape("supercomplex")
var aFrame = new Frame("f1")
aComplexShape.setFrame(aFrame)
console.log(aComplexShape.getFrame())
aCanvas.addShape(aSquare)
aCanvas.addShape(aComplexShape)
console.log("Shapes in aCanvas: "+Object.keys(aCanvas.getShapes()).length)
anotherCanvas.addShape(aCanvas.removeShape("supercomplex"))
console.log("Shapes in aCanvas: "+Object.keys(aCanvas.getShapes()).length)
console.log("Shapes in anotherCanvas: "+Object.keys(anotherCanvas.getShapes()).length)
console.log(aSquare instanceof Shape)
console.log(aComplexShape instanceof Shape)

This is an example that works out of the box. If you want less "hacky", you should use inheritance library or such.
Well in a file animal.js you would write:
var method = Animal.prototype;
function Animal(age) {
this._age = age;
}
method.getAge = function() {
return this._age;
};
module.exports = Animal;
To use it in other file:
var Animal = require("./animal.js");
var john = new Animal(3);
If you want a "sub class" then inside mouse.js:
var _super = require("./animal.js").prototype,
method = Mouse.prototype = Object.create( _super );
method.constructor = Mouse;
function Mouse() {
_super.constructor.apply( this, arguments );
}
//Pointless override to show super calls
//note that for performance (e.g. inlining the below is impossible)
//you should do
//method.$getAge = _super.getAge;
//and then use this.$getAge() instead of super()
method.getAge = function() {
return _super.getAge.call(this);
};
module.exports = Mouse;
Also you can consider "Method borrowing" instead of vertical inheritance. You don't need to inherit from a "class" to use its method on your class. For instance:
var method = List.prototype;
function List() {
}
method.add = Array.prototype.push;
...
var a = new List();
a.add(3);
console.log(a[0]) //3;

As Node.js community ensure new features from the JavaScript ECMA-262 specification are brought to Node.js developers in a timely manner.
You can take a look at JavaScript classes. MDN link to JS classes
In the ECMAScript 6 JavaScript classes are introduced, this method provide easier way to model OOP concepts in Javascript.
Note : JS classes will work in only strict mode.
Below is some skeleton of class,inheritance written in Node.js ( Used Node.js Version v5.0.0 )
Class declarations :
'use strict';
class Animal{
constructor(name){
this.name = name ;
}
print(){
console.log('Name is :'+ this.name);
}
}
var a1 = new Animal('Dog');
Inheritance :
'use strict';
class Base{
constructor(){
}
// methods definitions go here
}
class Child extends Base{
// methods definitions go here
print(){
}
}
var childObj = new Child();

I suggest to use the inherits helper that comes with the standard util module: http://nodejs.org/api/util.html#util_util_inherits_constructor_superconstructor
There is an example of how to use it on the linked page.

This is the best video about Object-Oriented JavaScript on the internet:
The Definitive Guide to Object-Oriented JavaScript
Watch from beginning to end!!
Basically, Javascript is a Prototype-based language which is quite different than the classes in Java, C++, C#, and other popular friends.
The video explains the core concepts far better than any answer here.
With ES6 (released 2015) we got a "class" keyword which allows us to use Javascript "classes" like we would with Java, C++, C#, Swift, etc.
Screenshot from the video showing how to write and instantiate a Javascript class/subclass:

In the Javascript community, lots of people argue that OOP should not be used because the prototype model does not allow to do a strict and robust OOP natively. However, I don't think that OOP is a matter of langage but rather a matter of architecture.
If you want to use a real strong OOP in Javascript/Node, you can have a look at the full-stack open source framework Danf. It provides all needed features for a strong OOP code (classes, interfaces, inheritance, dependency-injection, ...). It also allows you to use the same classes on both the server (node) and client (browser) sides. Moreover, you can code your own danf modules and share them with anybody thanks to Npm.

If you are working on your own, and you want the closest thing to OOP as you would find in Java or C# or C++, see the javascript library, CrxOop. CrxOop provides syntax somewhat familiar to Java developers.
Just be careful, Java's OOP is not the same as that found in Javascript. To get the same behavior as in Java, use CrxOop's classes, not CrxOop's structures, and make sure all your methods are virtual. An example of the syntax is,
crx_registerClass("ExampleClass",
{
"VERBOSE": 1,
"public var publicVar": 5,
"private var privateVar": 7,
"public virtual function publicVirtualFunction": function(x)
{
this.publicVar1 = x;
console.log("publicVirtualFunction");
},
"private virtual function privatePureVirtualFunction": 0,
"protected virtual final function protectedVirtualFinalFunction": function()
{
console.log("protectedVirtualFinalFunction");
}
});
crx_registerClass("ExampleSubClass",
{
VERBOSE: 1,
EXTENDS: "ExampleClass",
"public var publicVar": 2,
"private virtual function privatePureVirtualFunction": function(x)
{
this.PARENT.CONSTRUCT(pA);
console.log("ExampleSubClass::privatePureVirtualFunction");
}
});
var gExampleSubClass = crx_new("ExampleSubClass", 4);
console.log(gExampleSubClass.publicVar);
console.log(gExampleSubClass.CAST("ExampleClass").publicVar);
The code is pure javascript, no transpiling. The example is taken from a number of examples from the official documentation.

Related

Inheriting from a C++ class in JavaScript

I'm using V8 in a C++ program for extensions. I want to be able to
create objects in JavaScript that "inherit" from a base class in C++.
This is a simple hierarchy in C++:
class animal
{
public:
void move();
virtual void vocalize() = 0;
};
class cat : public animal
{
public:
void vocalize() override;
void ignore_owner();
};
This is cat implemented in JavaScript instead of C++:
function cat()
{
this.vocalize = function() {}
this.ignore_owner = function() {}
}
add_animal(new cat);
where add_animal() is a global function implemented in C++:
void add_animal(v8::Local<v8::Object> o);
In add_animal(), I manually add the move property pointing to a C++
function and make sure that the vocalize property exists and is a
function.
var c = new cat;
c.ignore_owner(); // JavaScript code
c.move(); // error, undefined
add_animal(c);
c.move(); // okay, C++ code
My experience in JavaScript outside of web pages is limited. Is this a
scheme that makes sense? The fact that add_animal() is used to both
add the "base class" properties and add the animal to a list looks
counter-intuitive to me. I could add a second function:
var c = new cat;
make_animal(c);
add_animal(c);
but this requires discipline and looks convoluted.
I could also expose animal, use it to create objects and add the
cat-specific properties afterwards:
function make_cat(c)
{
c.vocalize = function() {}
c.ignore_owner = function() {}
}
var c = new animal;
make_cat(c);
add_animal(c);
but this looks weird to me.
What is the best way to "inherit" from a C++ class?
Just expose your base class to JavaScript (see the official embedder's guide for an example), and then use regular JavaScript inheritance:
function Cat(name) {
this.name = name;
}
var catproto = Cat.prototype = new Animal();
catproto.vocalize = function() { /* cat-specific override */ }
catproto.ignore_owner = function() { return true; /* :-P */ }
catproto.purr = function() { /* you can add new methods too */ }
var c = new Cat("Kitty");
c.move(); // Inherited.
c.vocalize(); // Meow.

Is there a rather complete definition of a JavaScript class [duplicate]

I'm new in javascript.
How can I declare a class in javascript for example with property that named username.
then after username property valued a function is run.
In C# it is something like this :
public int M_A
{
get
{
return m_a;
}
set
{
m_a = value;
RunFunction();
}
}
Javascript doesn't have a class-based inheritance, it uses a prototype-based. Additionally, it doesn't provide support for getters and setters (in most versions).
Here would be one way to write your example:
var ExampleClass = function(){
var _m_a;//private instance
this.m_a = function(){
if(arguments.length){
_m_a = arguments[0];
}else{
return _m_a;
}
};
};
Usage:
var inst = new ExampleClass();
inst.m_a(5);//provide an argument to set it
console.log(inst.m_a());//no arguments to get it
Since we're just approximating a class system, there's actually a couple ways to do this. Here's another:
var ExampleClass = function(){
this._m_a = null;
};
ExampleClass.prototype.get_m_a = function(){
return this._m_a;
};
ExampleClass.prototype.set_m_a = function(value){
this._m_a = value;
};
Usage:
var inst = new ExampleClass();
inst.set_m_a(5);
console.log(inst.get_m_a());
console.log(inst._m_a);//annoying thing is the private property is accessible
For a better understanding of prototypal inheritance and javascript class systems, check out these posts:
Simple JavaScript Inheritance by John Resig (creator of jQuery)
Classical Inheritance in JavaScript by Douglas Crockford
JS Class - a Class framework for javascript
You can do something like this:
var M_A = function()
{
var m_a; //private variable
this.get = function()
{
return m_a;
}
this.set = function(value)
{
m_a = value;
RunFunction(); //run some global or private function
this.runPublic(); // run a public function
}
}
Then you can do:
var ma = new M_A();
ma.set(16);
alert(ma.get()); //alerts `16`
Demo: http://jsfiddle.net/maniator/72bnW/

Javascript OOP framework

I am wondering if the following code I have put together is the best way to define wrapper function for creating classes in js.
Does anyone have a better example willing to share as I thought of this as a first attempt.
What am I missing if anything?
j = {
context : {}
};
j.namepsace = (function(){
var createnamespace = function(parent, remainder){
if(remainder.length === 0){
return;
}
parent[remainder[0]] = parent[remainder[0]] || {};
return createnamespace(parent[remainder[0]], remainder.splice(1));
};
return {
define : function(ns){
createnamespace(j.context, ns.split('.'));
}
}
}());
j.class = (function(){
return {
construct : function(namespace, name, ctor){
namespace[name] = ctor;
},
ctor : function(namespace, name, ctor, prototype){
for (var property in prototype) {
if (prototype.hasOwnProperty(property)) {
ctor.prototype[property] = prototype[property];
}
}
namespace[name] = ctor;
}
}
}());
j.mixin = (function(){
return {
with : function(object, objectliteral){
for (var prototype in objectliteral) {
if (objectliteral.hasOwnProperty(prototype)) {
object[prototype] = objectliteral[prototype];
}
}
},
toDefintion : function(classdefinition, mixin){
var objectliteral = mixin();
for (var property in objectliteral) {
if (objectliteral.hasOwnProperty(property)) {
classdefinition.prototype[property] = objectliteral[property];
}
}
}
};
}());
j.namepsace.define('application.section');
j.class.construct(j.context.application.section,'printNameMixin', function(){
return {
printName : function(){
console.log(this.name);
}
};
});
j.class.construct(j.context.application.section,'person',function(name, address, age){
return {
name : name,
address : address,
age : age
};
});
j.class.ctor(j.context.application.section,'customer',function(name){
this.name = name;
}, {
name : 'unregistered client'
});
j.mixin.toDefintion(j.context.application.section.customer, j.context.application.section.printNameMixin );
var person = j.context.application.section.person('Blair Davidson','23 Test St',33);
var cust = new j.context.application.section.customer("Bankwest");
cust.printName();
console.log(person);
Your approach is interesting but as you asked for what is wrong, I would note 3 things:
1. Prototype
With your method, you breaks the mechanism of the prototype chain which is one of the power of javascript.
2. Inheritance
The mixin pattern is not my favorite pattern because it is often used to simulate multiple inheritance. But as the Single Responsability Principle and the fact that an inheritance should only be used to factorize code between classes having the same responsability suggest it, multiple inheritance should be avoided in a good OOP design.
3. OOP
If you want to do some strong OOP, you certainly need more features than that (like interfaces, dependency injection, ...). For this, I would suggest you to take a look at existing frameworks because it is a really long task (believe me). You can see an example of that kind of framework following the link in my profile (this is a javascript framework only working with nodejs but that you can use on both client (browser) and server (nodejs) side).

Viable method to do Multiple Inheritance in Javascript

I found this post about inheritance in javascript which I think is one of the best I've found on the web but this post can't be use for Multiple Inheritance because it will override the prototype methods and variables of past Super Class
ref : Javascript inheritance: call super-constructor or use prototype chain?
I would like to know if there's a way to do multiple inheritance with the principle of the "surrogate constructor" (see stack overflow ref post).
I've tried this method and I think it works great but I would like other opinions about limition, if there is, about this implementation.
You'll need jQuery to run this or just use this jsFiddle : http://jsfiddle.net/NGr2L/
Function.prototype.extend = function(p_parent){
function ctor() {};
//My trick for the Multiple Inheritance is to use the jQuery.extend method
ctor.prototype = $.extend({}, this.prototype, p_parent.prototype);
this.prototype = new ctor();
// I commentd this line of the reference post answer
//because it created multiple constructor which I found confusing
//this.prototype.constructor = this;
}
var Color = (function(){
//Constructor
function Color (p_color){
//Priviligied
this.color = p_color;
//Private
//...
};
//Public
Color.prototype.GetFormattedColor = function(){
return "I'm " + this.color;
};
return Color;
})();
var Animal = (function(){
//Constructor
function Animal (p_name){
//Priviligied
this.name = p_name;
//Private
//...
};
//Public
Animal.prototype.GetFormattedName = function(){
return "my name is " + this.name;
};
return Animal;
})();
var Tiger = (function(){
//Constructor
function Tiger (p_name, p_color, p_kindOfTiger){
//Base constructor
Color.call(this, p_color);
Animal.call(this, p_name);
//Priviligied
this.kindOfTiger = p_kindOfTiger;
//Private
//...
};
//Inheritance
Tiger.extend(Color); //I know, I could've loop
Tiger.extend(Animal);// on the "extend()" arguments to do this in one call
//Public
Tiger.prototype.GetTiger = function(){
return "I'm a " + this.kindOfTiger + ", " +
this.GetFormattedName() + " and " +
this.GetFormattedColor()
};
return Tiger;
})();
var myTiger = new Tiger("Boris", "Aqua", "bengal tiger");
myTiger.GetTiger();
Thank you very much
The best way of implementing multiple inheritance is composition.
Let's say we have a class Orange which extends (inherits from) classes Fruit and Color. Each of the 2 classes will have their own constructors and methods.
The main problem with multiple inheritance is that the methods in parent classes may collide.
function Colour(shade) {
this.shade = shade;
}
Colour.prototype.describe = function() {
console.log('Colour of shade', this.shade);
}
function Fruit(type) {
this.type = type;
}
Fruit.prototype.describe = function() {
console.log('Fruit of type', this.type);
}
function Orange() {}
Orange.prototype.describe = function() {
this.constructor.describe(); // which describe to call?
console.log('Orange');
}
multipleExtend(Orange, [Fruit, Colour]);
To avoid namespace collisions, the best way out is to use composition over inheritance.
function Orange() {
this._colour = new Colour('orange');
this._fruit = new Fruit('orange');
}
Orange.prototype.describe = function() {
this._colour.describe();
this._fruit.describe();
console.log('Orange');
}
A compromise of a solution can be achieved by extending one class and composing the other - but the choice of which classes to extend and which ones to compose may not be pragmatic.
PS: Inheriting and extending means the same thing (preventing possible confusions).
Edit 1
After spending some time on the idea of multiple-inheritance in JS, I came up with a design that captures the basic idea.
Unfortunately, I couldn't fit the whole thing in the size of an SO answer, so I made it into an article. You'll see that your "surrogate constructor" is what I call the inheritsMultipleConstructors() function.
The decision for the most suitable approach has to reflect the relationship of Color, Animal and Tiger. A tiger obviously is an animal, both animal and tiger might feature a color (tiger has a color). Thus inheritance only applies for Animal <= Tiger. A Color could be acquired by composition. But here aggregation will be the more favorable choice. Thus the Tiger class does contain a colorfield of type Color.
Real class based mutliple inheritance (inheriting directly from more than one prototype a time) technically is not possible in JS. But function based composition is a very handy tool as well. For the provided example there will be two additional behaviors that not that accidentally feature a describeThyself method name each, which already is in use by e.g. some class implementations. Thus in addition to the composition part, the behaviors also need to take care of conflict resolution.
For reasons of comfort the provided example code does feature class syntax ...
class Color {
constructor(colorValue) {
this.color = colorValue;
}
describeThyself() {
return `I'm colored ${this.color}.`;
}
}
class Animal {
constructor(speciesName) {
this.species = speciesName;
}
describeThyself() {
return `My species is called ${this.species}.`;
}
}
function withNormalHuntingBehavior() { // function based mixin.
function describeThyself() {
return 'I mostly feed on herbivorous mammals.';
}
if (this.describeThyself) { // - conflict resolution
this.describeThyself = (function (proceed) {
return function () { // - function composition
var result = proceed.apply(this/*, arguments*/);
return (result + ' ' + describeThyself.call(this/*, result, arguments*/));
}
}(this.describeThyself));
} else {
this.describeThyself = describeThyself;
}
return this;
}
function withManEatingBehavior() { // function based mixin.
function describeThyself() {
return 'I ocassionally kill and eat humans too.';
}
if (this.describeThyself) { // - conflict resolution
this.describeThyself = (function (proceed) {
return function () { // - function composition
var result = proceed.apply(this/*, arguments*/);
return (result + ' ' + describeThyself.call(this/*, result, arguments*/));
}
}(this.describeThyself));
} else {
this.describeThyself = describeThyself;
}
return this;
}
class Tiger extends Animal { // - inheritance part I.
constructor(subspeciesName, colorValue) {
super('Tiger'); // - inheritance part II.
this.subspecies = subspeciesName;
this.color = (new Color(colorValue)); // - aggregation.
}
describeThyself() {
return [
super.describeThyself.call(this), // - super delegation.
`I'm of the "${this.subspecies}" subspecies.`,
`And ${this.color.describeThyself()}` // - forwarding.
].join(' ');
}
}
// - composition at prototype level.
withNormalHuntingBehavior.call(Tiger.prototype);
function createBengalTiger(colorValue) { // bengal tiger factory
var
tiger = new Tiger('Bengal Tiger', colorValue);
// composition at instance level.
return withManEatingBehavior.call(tiger);
}
var siberianTiger = new Tiger('Siberian Tiger', 'kind of pale orange/reddish-something');
var bengalTiger = createBengalTiger("bright reddish-gold");
console.log('siberianTiger.describeThyself() : ' + siberianTiger.describeThyself());
console.log('bengalTiger.describeThyself() : ' + bengalTiger.describeThyself());
.as-console-wrapper { max-height: 100%!important; top: 0; }

What techniques can be used to define a class in JavaScript, and what are their trade-offs?

I prefer to use OOP in large scale projects like the one I'm working on right now. I need to create several classes in JavaScript but, if I'm not mistaken, there are at least a couple of ways to go about doing that. What would be the syntax and why would it be done in that way?
I would like to avoid using third-party libraries - at least at first.
Looking for other answers, I found the article Object-Oriented Programming with JavaScript, Part I: Inheritance - Doc JavaScript that discusses object-oriented programming in JavaScript. Is there a better way to do inheritance?
Here's the way to do it without using any external libraries:
// Define a class like this
function Person(name, gender){
// Add object properties like this
this.name = name;
this.gender = gender;
}
// Add methods like this. All Person objects will be able to invoke this
Person.prototype.speak = function(){
alert("Howdy, my name is" + this.name);
};
// Instantiate new objects with 'new'
var person = new Person("Bob", "M");
// Invoke methods like this
person.speak(); // alerts "Howdy, my name is Bob"
Now the real answer is a whole lot more complex than that. For instance, there is no such thing as classes in JavaScript. JavaScript uses a prototype-based inheritance scheme.
In addition, there are numerous popular JavaScript libraries that have their own style of approximating class-like functionality in JavaScript. You'll want to check out at least Prototype and jQuery.
Deciding which of these is the "best" is a great way to start a holy war on Stack Overflow. If you're embarking on a larger JavaScript-heavy project, it's definitely worth learning a popular library and doing it their way. I'm a Prototype guy, but Stack Overflow seems to lean towards jQuery.
As far as there being only "one way to do it", without any dependencies on external libraries, the way I wrote is pretty much it.
The best way to define a class in JavaScript is to not define a class.
Seriously.
There are several different flavors of object-orientation, some of them are:
class-based OO (first introduced by Smalltalk)
prototype-based OO (first introduced by Self)
multimethod-based OO (first introduced by CommonLoops, I think)
predicate-based OO (no idea)
And probably others I don't know about.
JavaScript implements prototype-based OO. In prototype-based OO, new objects are created by copying other objects (instead of being instantiated from a class template) and methods live directly in objects instead of in classes. Inheritance is done via delegation: if an object doesn't have a method or property, it is looked up on its prototype(s) (i.e. the object it was cloned from), then the prototype's prototypes and so on.
In other words: there are no classes.
JavaScript actually has a nice tweak of that model: constructors. Not only can you create objects by copying existing ones, you can also construct them "out of thin air", so to speak. If you call a function with the new keyword, that function becomes a constructor and the this keyword will not point to the current object but instead to a newly created "empty" one. So, you can configure an object any way you like. In that way, JavaScript constructors can take on one of the roles of classes in traditional class-based OO: serving as a template or blueprint for new objects.
Now, JavaScript is a very powerful language, so it is quite easy to implement a class-based OO system within JavaScript if you want to. However, you should only do this if you really have a need for it and not just because that's the way Java does it.
ES2015 Classes
In the ES2015 specification, you can use the class syntax which is just sugar over the prototype system.
class Person {
constructor(name) {
this.name = name;
}
toString() {
return `My name is ${ this.name }.`;
}
}
class Employee extends Person {
constructor(name, hours) {
super(name);
this.hours = hours;
}
toString() {
return `${ super.toString() } I work ${ this.hours } hours.`;
}
}
Benefits
The main benefit is that static analysis tools find it easier to target this syntax. It is also easier for others coming from class-based languages to use the language as a polyglot.
Caveats
Be wary of its current limitations. To achieve private properties, one must resort to using Symbols or WeakMaps. In future releases, classes will most likely be expanded to include these missing features.
Support
Browser support isn't very good at the moment (supported by nearly everyone except IE), but you can use these features now with a transpiler like Babel.
Resources
Classes in ECMAScript 6 (final semantics)
What? Wait. Really? Oh no! (a post about ES6 classes and privacy)
Compatibility Table – Classes
Babel – Classes
I prefer to use Daniel X. Moore's {SUPER: SYSTEM}. This is a discipline that provides benefits such as true instance variables, trait based inheritance, class hierarchies and configuration options. The example below illustrates the use of true instance variables, which I believe is the biggest advantage. If you don't need instance variables and are happy with only public or private variables then there are probably simpler systems.
function Person(I) {
I = I || {};
Object.reverseMerge(I, {
name: "McLovin",
age: 25,
homeState: "Hawaii"
});
return {
introduce: function() {
return "Hi I'm " + I.name + " and I'm " + I.age;
}
};
}
var fogel = Person({
age: "old enough"
});
fogel.introduce(); // "Hi I'm McLovin and I'm old enough"
Wow, that's not really very useful on it's own, but take a look at adding a subclass:
function Ninja(I) {
I = I || {};
Object.reverseMerge(I, {
belt: "black"
});
// Ninja is a subclass of person
return Object.extend(Person(I), {
greetChallenger: function() {
return "In all my " + I.age + " years as a ninja, I've never met a challenger as worthy as you...";
}
});
}
var resig = Ninja({name: "John Resig"});
resig.introduce(); // "Hi I'm John Resig and I'm 25"
Another advantage is the ability to have modules and trait based inheritance.
// The Bindable module
function Bindable() {
var eventCallbacks = {};
return {
bind: function(event, callback) {
eventCallbacks[event] = eventCallbacks[event] || [];
eventCallbacks[event].push(callback);
},
trigger: function(event) {
var callbacks = eventCallbacks[event];
if(callbacks && callbacks.length) {
var self = this;
callbacks.forEach(function(callback) {
callback(self);
});
}
},
};
}
An example of having the person class include the bindable module.
function Person(I) {
I = I || {};
Object.reverseMerge(I, {
name: "McLovin",
age: 25,
homeState: "Hawaii"
});
var self = {
introduce: function() {
return "Hi I'm " + I.name + " and I'm " + I.age;
}
};
// Including the Bindable module
Object.extend(self, Bindable());
return self;
}
var person = Person();
person.bind("eat", function() {
alert(person.introduce() + " and I'm eating!");
});
person.trigger("eat"); // Blasts the alert!
Disclosure: I am Daniel X. Moore and this is my {SUPER: SYSTEM}. It is the best way to define a class in JavaScript.
var Animal = function(options) {
var name = options.name;
var animal = {};
animal.getName = function() {
return name;
};
var somePrivateMethod = function() {
};
return animal;
};
// usage
var cat = Animal({name: 'tiger'});
Following are the ways to create objects in javascript, which I've used so far
Example 1:
obj = new Object();
obj.name = 'test';
obj.sayHello = function() {
console.log('Hello '+ this.name);
}
Example 2:
obj = {};
obj.name = 'test';
obj.sayHello = function() {
console.log('Hello '+ this.name);
}
obj.sayHello();
Example 3:
var obj = function(nameParam) {
this.name = nameParam;
}
obj.prototype.sayHello = function() {
console.log('Hello '+ this.name);
}
Example 4: Actual benefits of Object.create(). please refer [this link]
var Obj = {
init: function(nameParam) {
this.name = nameParam;
},
sayHello: function() {
console.log('Hello '+ this.name);
}
};
var usrObj = Object.create(Obj); // <== one level of inheritance
usrObj.init('Bob');
usrObj.sayHello();
Example 5 (customised Crockford's Object.create):
Object.build = function(o) {
var initArgs = Array.prototype.slice.call(arguments,1)
function F() {
if((typeof o.init === 'function') && initArgs.length) {
o.init.apply(this,initArgs)
}
}
F.prototype = o
return new F()
}
MY_GLOBAL = {i: 1, nextId: function(){return this.i++}} // For example
var userB = {
init: function(nameParam) {
this.id = MY_GLOBAL.nextId();
this.name = nameParam;
},
sayHello: function() {
console.log('Hello '+ this.name);
}
};
var bob = Object.build(userB, 'Bob'); // Different from your code
bob.sayHello();
To keep answer updated with ES6/ ES2015
A class is defined like this:
class Person {
constructor(strName, numAge) {
this.name = strName;
this.age = numAge;
}
toString() {
return '((Class::Person) named ' + this.name + ' & of age ' + this.age + ')';
}
}
let objPerson = new Person("Bob",33);
console.log(objPerson.toString());
I think you should read Douglas Crockford's Prototypal Inheritance in JavaScript and Classical Inheritance in JavaScript.
Examples from his page:
Function.prototype.method = function (name, func) {
this.prototype[name] = func;
return this;
};
Effect? It will allow you to add methods in more elegant way:
function Parenizor(value) {
this.setValue(value);
}
Parenizor.method('setValue', function (value) {
this.value = value;
return this;
});
I also recommend his videos:
Advanced JavaScript.
You can find more videos on his page: http://javascript.crockford.com/
In John Reisig book you can find many examples from Douglas Crockfor's website.
Because I will not admit the YUI/Crockford factory plan and because I like to keep things self contained and extensible this is my variation:
function Person(params)
{
this.name = params.name || defaultnamevalue;
this.role = params.role || defaultrolevalue;
if(typeof(this.speak)=='undefined') //guarantees one time prototyping
{
Person.prototype.speak = function() {/* do whatever */};
}
}
var Robert = new Person({name:'Bob'});
where ideally the typeof test is on something like the first method prototyped
If you're going for simple, you can avoid the "new" keyword entirely and just use factory methods. I prefer this, sometimes, because I like using JSON to create objects.
function getSomeObj(var1, var2){
var obj = {
instancevar1: var1,
instancevar2: var2,
someMethod: function(param)
{
//stuff;
}
};
return obj;
}
var myobj = getSomeObj("var1", "var2");
myobj.someMethod("bla");
I'm not sure what the performance hit is for large objects, though.
var Student = (function () {
function Student(firstname, lastname) {
this.firstname = firstname;
this.lastname = lastname;
this.fullname = firstname + " " + lastname;
}
Student.prototype.sayMyName = function () {
return this.fullname;
};
return Student;
}());
var user = new Student("Jane", "User");
var user_fullname = user.sayMyName();
Thats the way TypeScript compiles class with constructor to JavaScript.
The simple way is:
function Foo(a) {
var that=this;
function privateMethod() { .. }
// public methods
that.add = function(b) {
return a + b;
};
that.avg = function(b) {
return that.add(b) / 2; // calling another public method
};
}
var x = new Foo(10);
alert(x.add(2)); // 12
alert(x.avg(20)); // 15
The reason for that is that this can be bound to something else if you give a method as an event handler, so you save the value during instantiation and use it later.
Edit: it's definitely not the best way, just a simple way. I'm waiting for good answers too!
You probably want to create a type by using the Folding Pattern:
// Here is the constructor section.
var myType = function () {
var N = {}, // Enclosed (private) members are here.
X = this; // Exposed (public) members are here.
(function ENCLOSED_FIELDS() {
N.toggle = false;
N.text = '';
}());
(function EXPOSED_FIELDS() {
X.count = 0;
X.numbers = [1, 2, 3];
}());
// The properties below have access to the enclosed fields.
// Careful with functions exposed within the closure of the
// constructor, each new instance will have it's own copy.
(function EXPOSED_PROPERTIES_WITHIN_CONSTRUCTOR() {
Object.defineProperty(X, 'toggle', {
get: function () {
var before = N.toggle;
N.toggle = !N.toggle;
return before;
}
});
Object.defineProperty(X, 'text', {
get: function () {
return N.text;
},
set: function (value) {
N.text = value;
}
});
}());
};
// Here is the prototype section.
(function PROTOTYPE() {
var P = myType.prototype;
(function EXPOSED_PROPERTIES_WITHIN_PROTOTYPE() {
Object.defineProperty(P, 'numberLength', {
get: function () {
return this.numbers.length;
}
});
}());
(function EXPOSED_METHODS() {
P.incrementNumbersByCount = function () {
var i;
for (i = 0; i < this.numbers.length; i++) {
this.numbers[i] += this.count;
}
};
P.tweak = function () {
if (this.toggle) {
this.count++;
}
this.text = 'tweaked';
};
}());
}());
That code will give you a type called myType. It will have internal private fields called toggle and text. It will also have these exposed members: the fields count and numbers; the properties toggle, text and numberLength; the methods incrementNumbersByCount and tweak.
The Folding Pattern is fully detailed here:
Javascript Folding Pattern
Code golf for #liammclennan's answer.
var Animal = function (args) {
return {
name: args.name,
getName: function () {
return this.name; // member access
},
callGetName: function () {
return this.getName(); // method call
}
};
};
var cat = Animal({ name: 'tiger' });
console.log(cat.callGetName());
MooTools (My Object Oriented Tools) is centered on the idea of classes. You can even extend and implement with inheritance.
When mastered, it makes for ridiculously reusable, powerful javascript.
Object Based Classes with Inheritence
var baseObject =
{
// Replication / Constructor function
new : function(){
return Object.create(this);
},
aProperty : null,
aMethod : function(param){
alert("Heres your " + param + "!");
},
}
newObject = baseObject.new();
newObject.aProperty = "Hello";
anotherObject = Object.create(baseObject);
anotherObject.aProperty = "There";
console.log(newObject.aProperty) // "Hello"
console.log(anotherObject.aProperty) // "There"
console.log(baseObject.aProperty) // null
Simple, sweet, and gets 'er done.
Based on the example of Triptych, this might even be simpler:
// Define a class and instantiate it
var ThePerson = new function Person(name, gender) {
// Add class data members
this.name = name;
this.gender = gender;
// Add class methods
this.hello = function () { alert('Hello, this is ' + this.name); }
}("Bob", "M"); // this instantiates the 'new' object
// Use the object
ThePerson.hello(); // alerts "Hello, this is Bob"
This only creates a single object instance, but is still useful if you want to encapsulate a bunch of names for variable and methods in a class. Normally there would not be the "Bob, M" arguments to the constructor, for example if the methods would be calls to a system with its own data, such as a database or network.
I am still too new with JS to see why this does not use the prototype thing.
A base
function Base(kind) {
this.kind = kind;
}
A class
// Shared var
var _greeting;
(function _init() {
Class.prototype = new Base();
Class.prototype.constructor = Class;
Class.prototype.log = function() { _log.apply(this, arguments); }
_greeting = "Good afternoon!";
})();
function Class(name, kind) {
Base.call(this, kind);
this.name = name;
}
// Shared function
function _log() {
console.log(_greeting + " Me name is " + this.name + " and I'm a " + this.kind);
}
Action
var c = new Class("Joe", "Object");
c.log(); // "Good afternoon! Me name is Joe and I'm a Object"
JavaScript is object-oriented, but it's radically different than other OOP languages like Java, C# or C++. Don't try to understand it like that. Throw that old knowledge out and start anew. JavaScript needs a different thinking.
I'd suggest to get a good manual or something on the subject. I myself found ExtJS Tutorials the best for me, although I haven't used the framework before or after reading it. But it does give a good explanation about what is what in JavaScript world. Sorry, it seems that that content has been removed. Here's a link to archive.org copy instead. Works today. :P
//new way using this and new
function Persons(name) {
this.name = name;
this.greeting = function() {
alert('Hi! I\'m ' + this.name + '.');
};
}
var gee=new Persons("gee");
gee.greeting();
var gray=new Persons("gray");
gray.greeting();
//old way
function createPerson(name){
var obj={};
obj.name=name;
obj.greeting = function(){
console.log("hello I am"+obj.name);
};
return obj;
}
var gita=createPerson('Gita');
gita.greeting();

Categories

Resources