Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
I am aware of general Object-oriented programming principles like Encapsulation, Inheritance, Polymorphism, Abstraction, etc
But would now want to understand these concepts from a JavaScript perspective.
Could someone take a very basic example and run how these works in JS context (Encapsulation, Inheritance, Polymorphism, Abstraction)
I have read a lot about these online, but the articles have left me more confused.
Thank you.
I will describe the Douglas Crockford Pattern to mimic the style used in Object-Oriented Programming languages. It doesn't use prototypal inheritance. As a result, it's slightly less efficient because each object has to store a reference to each method. But it's very useful for illustrative purposes.
Encapsulation:
function MyClass (a, b)
{
this.publicProperty = 1;
var _privateProperty = 2;
function _privateMethod () {
// only private methods and privileged methods can call this
};
this.publicMethod = function () {
// can access _privateProperty and call _privateMethod
};
}
MyClass.classMethod = function () {
// not tied to any instances
};
Simply create objects with var instance = new MyClass(a, b);
Inheritance:
function DerivedClass(a, b, c)
{
// must explicitly call superclass constructor, like in Java
MyClass.apply(this, arguments);
this.anotherProperty = 3;
function _anotherPrivateMethod() { };
this.publicMethod = function () {
// can access _privateProperty and call _privateMethod
};
}
DerivedClass.classMethodMethod = function ()
{
// not tied to any instances
};
Polymorphism in JavaScript is mostly replaced by Duck Typing (http://en.wikipedia.org/wiki/Duck_typing). Developers usually group methods/properties under objects, and you just test for the presence of those objects. This is how newfangles browser capabilities are detected, for instance.
Abstraction is closely tied with the polymorphism - as long as something supports an interface, you don't usually care how it works underneath. Thus, you may download a Javascript library and just use it, based on its documentation.
Hope this helps.
I think the most interesting is encapsulation as a lot of people don't use it properly.
Lets take a simple object as an example
var Person = function( firstName, lastName, isMr ) {
var prefix = isMr ? "Mr." : "Mrs." ;
this.getFullName = function() { return prefix + " "
+ firstName + " " + lastName }
}
var p = new Person ("guy","mograbi", true);
p.getFullName(); // => "Mr. guy mograbi"
// p.prefix ==> causes an error.
Inheritance - is simply extending the prototype
var Superhero = function(){
Person.call(this);
}
However proper inheritance is an issue by itself.
Check out https://stackoverflow.com/a/4985616/1068746
Polymorphism - is quite simple, given a new prototype that implements "getFullName"
var Child = function(){
this.getFullName = function(){ return "not allowed to talk with strangers" }
}
given function(a){ a.getFullName() }
You will get full name if a is Person and "not allowed.." if a is Child.
Abstraction - is more of a type-safe language thing.
https://stackoverflow.com/a/4082496/1068746
You can use a function to define a singleton object
var apple = new function() {
this.type = "macintosh";
this.color = "red";
this.getInfo = function () {
return this.color + ' ' + this.type + ' apple';
};
}
use it as given below
apple.color = "reddish";
alert(apple.getInfo());
new function(){...} does two things at the same time: define a function (an anonymous constructor function) and invoke it with new.
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
I'm writing a small example to call function getAge() to display age via an object.
I've 3 ways to do that:
"use strict";
var personClass = class {
static getAge() {
return 18
}
};
var personJSON = {
getAge: function () {
return 18
}
};
function personFunc() {
var getAge = function () {
return 18
};
// set a flag to point to getAge function
this.getAge = getAge()
}
$('#btn1').click(function () {
alert(personClass.getAge())
});
$('#btn2').click(function () {
alert(personJSON.getAge())
});
$('#btn3').click(function () {
var p = new personFunc();
alert(p.getAge)
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="btn1">Get age via class</button>
<button id="btn2">Get age via json</button>
<button id="btn3">Get age via function</button>
My question: What's the best way? And why?
It depends on the actual problem you have to solve and the style of programming you're using. If you tend to use an object oriented approach and want to benfit from it's features like inheritance you might want to model a person as
function Person(){
var age = 18;
this.getAge = function() {
return age;
}
}
var person = new Person();
alert(p.getAge());
Or as a class
class Person {
constructor() {
this.age = 18;
}
getAge() {
return this.age()
}
}
If you prefer a more functional style, you'll write pure and independent functions that perform some action on some data:
// does not make much sense in this age of a person context
function age(obj, dateFn) {
return dateFn() - obj.born;
}
var person = { born : new Date(/* */) }
var animal = { born : new Date(/* */) }
alert(age(person, Date.now));
alert(age(animal, Date.UTC));
For the example of getAge, any kind of static function does not make any sense (your first example), since age is the property of some object. So you'll need an instance of an object which you can use to call a method, or to pass to a function.
I would recommend the most simple form:
var personJSON = {
getAge: function () {
return 18;
}
};
It already creates a well-defined object with the desired properties, it scales well and it is not encumbered by red-tape boilerplate code.
Good code already did so for years and it is a very well proven style. It is readable and compact.
What you will NOT get from this are the new advanced features of ES6 class definitions which might be required in more advanced cases.
Warning! This is just my personal, biased opinion:
I, for one, will not use class definitions at all, instead I will leverage this style and lambdas, as I've always done in 10+ years. I'm also contrary to the introduction of syntactical sugar in Javascript just to let it look like other languages. I prefer the prototypical paradigm.
I'm just saying how I would use the three. This is not meant to be an absolute answer, this is the way I see things. And I'm interested to see other people points of view on this.
class
I'd only use this key word in case I want to instantiate multiple times this object. (Only available in ECMAScript 6)
"use strict"
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(this.name + ' makes a noise.');
}
}
class Dog extends Animal {
speak() {
console.log(this.name + ' barks.');
}
}
var bobby = new Dog("Bobby");
bobby.speak();
JSON
I'd only declare a JSON when I'm only going to instantiate it once.
var Game = {
run: function() {
//...
},
stop: function() {
//...
},
pause: function() {
//...
},
maxPlayer: 4,
rooms: [{
roomName: "Room1",
playerNames: ["Player1", "Player2"]
}, {
roomName: "Room2",
playerNames: ["Player1", "Player2", "Player3"]
}]
};
function
You're using it more like a class substitute here. By using new keyword you can instantiate this function as a class as many times as you want. (Which a lot a people do and that's ok ! Mostly because the keyword class is only available in ECMAScript 6)
var Person = function (firstName) {
this.firstName = firstName;
};
Person.prototype.sayHello = function() {
console.log("Hello, I'm " + this.firstName);
};
var person1 = new Person("Alice");
person1.sayHello();
I would suggest something like this. I'd be curious to hear other people's feedback.
//Convention says use capital case if declaring a function as a class.
function Person(age){
//Optional: allow the developer to pass in an age when creating the object
//Otherwise default to 18
this.age = age? age: 18; //ternary operator
//function declaration.
this.getAge = function() {
return this.age;
}
}
$('#btn3').click(function () {
var p = new Person();
alert(p.getAge()) //Alert 18
var p2 = new Person(15);
alert(p2.getAge()) //Alert 15
});
My reasoning for this is that this is an objected oriented way of doing it.
The capital case lets you know that this function is intended to be used with a with the new keyword.
Is reusable - you can have multiple, different Person objects, with different ages, without having to declare the methods each time for each one.
Syntax and usage is similar to object oriented languages like Java which one might already be familiar with.
The last way that you wrote is the best
function personFunc() {
var getAge = function () {
return 18
};
// set a flag to point to getAge function
this.getAge = getAge()
}
Buth there is a better one by perfomance, but little complex by writing. It is like TypeScript or Babel compiles it's classes to JavaScript.
function PersonClass() {
this.age = 18;
}
PersonClass.prototype.getAge = function () {
return this.age;
};
usage is the same:
var person = new PersonClass();
person.getAge();
But to write like this by yourself is little time-consuming. So I think that the best thing for now is to use ES6 classes and compile them with TypeScript or Babel.
So, my opinion is the best way to write like this:
class PersonClass {
private age = 18;
getAge() {
return this.age;
}
}
This question already has answers here:
How to implement C# access modifiers in javascript?
(5 answers)
Closed 1 year ago.
Note:
As the answers tell, the code proposed in the question does NOT really achieve inheritance(otherwise it becomes an answer rather than a question .. ) due to some issues described in the question and in my comments. It works as expected as a fake of inheritance(and not even prototypal).
Summary
In short, make it as similar as we are writing a general OO language rather than javascript, but keep the inheritance be correct.
The story
Object.create is a good way to achieve prototypal inheritance, but it's a bit confusing to a typed brain and new fans.
There are various ways that we can write javascript code more like we are writing other OO languages with the pseudo-classical pattern. As it's pseudo-classical, we must deal with the underlying prototypal inheritance of javascript correctly.
What I want to find is an approach that the pseudo-classical inheritance can be achieved right on the class declaration. The code for demonstration is put at the rear of the post, it works as expected, however, there are some annoying things:
I cannot get rid of return in the class declaration or the inheritance won't work.
I have no way except pass this in the class declaration to make the returning closure know what is this.
I also want to get rid of function (instance, _super) {, but not yet have a good idea.
The static(own properties) of a class are not inherited.
A solution would be more of some syntactic sugar than the existing frameworks, a good pattern is applicable.
The _extends function:
function _extends(baseType) {
return function (definition) {
var caller=arguments.callee.caller;
var instance=this;
if(!(instance instanceof baseType)) {
(caller.prototype=new baseType()).constructor=caller;
instance=new caller();
}
var _super=function () {
baseType.apply(instance, arguments);
};
definition(instance, _super);
return instance;
};
}
The Abc class:
function Abc(key, value) {
return _extends(Object).call(this, function (instance, _super) {
instance.What=function () {
alert('What');
};
instance.getValue=function () {
return 333+Number(value);
};
instance.Value=instance.getValue();
instance.Key=key;
});
}
The Xyz class:
function Xyz(key, value) {
return _extends(Abc).call(this, function (instance, _super) {
_super(key, value);
instance.That=function () {
alert('That');
};
});
}
Example code:
var x=new Xyz('x', '123');
alert([x.Key, x.Value].join(': ')+'; isAbc: '+(x instanceof Abc));
var y=new Xyz('y', '456');
alert([y.Key, y.Value].join(': ')+'; isAbc: '+(y instanceof Abc));
var it=new Abc('it', '789');
alert([it.Key, it.Value].join(': ')+'; isAbc: '+(it instanceof Abc));
alert([it.Key, it.Value].join(': ')+'; isXyz: '+(it instanceof Xyz));
x.What();
y.That();
it.What();
it.That(); // will throw; it is not Xyz and does not have That method
No. No. No. This won't do. You're doing inheritance in JavaScript all wrong. Your code gives me migraines.
Creating a Pseudo-Classical Inheritance Pattern in JavaScript
If you want something similar to classes in JavaScript then there are a lot of libraries out there which provide it to you. For example using augment you could restructure your code as follows:
var augment = require("augment");
var ABC = augment(Object, function () {
this.constructor = function (key, value) {
this.key = key;
this.value = value;
};
this.what = function () {
alert("what");
};
});
var XYZ = augment(ABC, function (base) {
this.constructor = function (key, value) {
base.constructor.call(this, key, value);
};
this.that = function () {
alert("that");
};
});
I don't know about you but to me this looks a lot like classical inheritance in C++ or Java. If this solves your problem, great! If is doesn't then continue reading.
Prototype-Class Isomorphism
In a lot of ways prototypes are similar to classes. In fact prototypes and classes are so similar that we can use prototypes to model classes. First let's take a look at how prototypal inheritance really works:
The above picture was taken from the following answer. I suggest you read it carefully. The diagram shows us:
Every constructor has a property called prototype which points to the prototype object of the constructor function.
Every prototype has a property called constructor which points to the constructor function of the prototype object.
We create an instance from a constructor function. However the instance actually inherits from the prototype, not the constructor.
This is very useful information. Traditionally we've always created a constructor function first and then we've set its prototype properties. However this information shows us that we may create a prototype object first and then define the constructor property on it instead.
For example, traditionally we may write:
function ABC(key, value) {
this.key = key;
this.value = value;
}
ABC.prototype.what = function() {
alert("what");
};
However using our newfound knowledge we may write the same thing as:
var ABC = CLASS({
constructor: function (key, value) {
this.key = key;
this.value = value;
},
what: function () {
alert("what");
}
});
function CLASS(prototype) {
var constructor = prototype.constructor;
constructor.prototype = prototype;
return constructor;
}
As you can see encapsulation is easy to achieve in JavaScript. All you need to do is think sideways. Inheritance however is a different issue. You need to do a little more work to achieve inheritance.
Inheritance and Super
Take a look at how augment achieves inheritance:
function augment(body) {
var base = typeof this === "function" ? this.prototype : this;
var prototype = Object.create(base);
body.apply(prototype, arrayFrom(arguments, 1).concat(base));
if (!ownPropertyOf(prototype, "constructor")) return prototype;
var constructor = prototype.constructor;
constructor.prototype = prototype;
return constructor;
}
Notice that the last three lines are the same as that of CLASS from the previous section:
function CLASS(prototype) {
var constructor = prototype.constructor;
constructor.prototype = prototype;
return constructor;
}
This tells us that once we have a prototype object all we need to do is get its constructor property and return it.
The first three lines of augment are used to:
Get the base class prototype.
Create a derived class prototype using Object.create.
Populate the derived class prototype with the specified properties.
That's all that there is to inheritance in JavaScript. If you want to create your own classical inheritance pattern then you should be thinking along the same lines.
Embracing True Prototypal Inheritance
Every JavaScript programmer worth their salt will tell you that prototypal inheritance is better than classical inheritance. Nevertheless newbies who come from a language with classical inheritance always try to implement classical inheritance on top of prototypal inheritance, and they usually fail.
They fail not because it's not possible to implement classical inheritance on top of prototypal inheritance but because to implement classical inheritance on top of prototypal inheritance you first need to understand how true prototypal inheritance works.
However once you understand true prototypal inheritance you'll never want to go back to classical inheritance. I too tried to implement classical inheritance on top of prototypal inheritance as a newbie. Now that I understand how true prototypal inheritance works however I write code like this:
function extend(self, body) {
var base = typeof self === "function" ? self.prototype : self;
var prototype = Object.create(base, {new: {value: create}});
return body.call(prototype, base), prototype;
function create() {
var self = Object.create(prototype);
return prototype.hasOwnProperty("constructor") &&
prototype.constructor.apply(self, arguments), self;
}
}
The above extend function is very similar to augment. However instead of returning the constructor function it returns the prototype object. This is actually a very neat trick which allows static properties to be inherited. You can create a class using extend as follows:
var Abc = extend(Object, function () {
this.constructor = function (key, value) {
this.value = 333 + Number(value);
this.key = key;
};
this.what = function () {
alert("what");
};
});
Inheritance is just as simple:
var Xyz = extend(Abc, function (base) {
this.constructor = function (key, value) {
base.constructor.call(this, key, value);
};
this.that = function () {
alert("that");
};
});
Remember however that extend does not return the constructor function. It returns the prototype object. This means that you can't use the new keyword to create an instance of the class. Instead you need to use new as a method, as follows:
var x = Xyz.new("x", "123");
var y = Xyz.new("y", "456");
var it = Abc.new("it", "789");
This is actually a good thing. The new keyword is considered harmful and I strongly recommend you to stop using it. For example it's not possible to use apply with the new keyword. However it is possible to use apply with the new method as follows:
var it = Abc.new.apply(null, ["it", "789"]);
Since Abc and Xyz are not constructor functions we can't use instanceof to test whether an object is an instance of Abc or Xyz. However that's not a problem because JavaScript has a method called isPrototypeOf which tests whether an object is a prototype of another object:
alert(x.key + ": " + x.value + "; isAbc: " + Abc.isPrototypeOf(x));
alert(y.key + ": " + y.value + "; isAbc: " + Abc.isPrototypeOf(y));
alert(it.key + ": " + it.value + "; isAbc: " + Abc.isPrototypeOf(it));
alert(it.key + ": " + it.value + "; isXyz: " + Xyz.isPrototypeOf(it));
In fact isPrototypeOf is more powerful than instanceof because it allows us to test whether one class extends another class:
alert(Abc.isPrototypeOf(Xyz)); // true
Besides this minor change everything else works just like it did before:
x.what();
y.that();
it.what();
it.that(); // will throw; it is not Xyz and does not have that method
See the demo for yourself: http://jsfiddle.net/Jee96/
What else does true prototypal inheritance offer? One of the biggest advantages of true prototypal inheritance is that there's no distinction between normal properties and static properties allowing you to write code like this:
var Xyz = extend(Abc, function (base) {
this.empty = this.new();
this.constructor = function (key, value) {
base.constructor.call(this, key, value);
};
this.that = function () {
alert("that");
};
});
Notice that we can create instances of the class from within the class itself by calling this.new. If this.constructor is not yet defined then it returns a new uninitialized instance. Otherwise it returns a new initialized instance.
In addition because Xyz is the prototype object we can access Xyz.empty directly (i.e. empty is a static property of Xyz). This also means that static properties are automatically inherited and are no different from normal properties.
Finally, because the class is accessible from within the class definition as this, you can created nested classes which inherit from the class which they are nested within by using extend as follows:
var ClassA = extend(Object, function () {
var ClassB = extend(this, function () {
// class definition
});
// rest of the class definition
alert(this.isPrototypeOf(ClassB)); // true
});
See the demo for yourself: http://jsfiddle.net/Jee96/1/
There's an exhaustive tutorial on how to do what you're after.
oop-concepts
pseudo-classical-pattern
all-one-constructor-pattern
I know this doesn't answer your question because as far as I know there is no good way to put everything in the function constructor and have it use prototype.
As I've commented; if you have trouble with the JavaScript syntax then typescript could be a good alternative.
Here is a helper function that I use for inheritance and overriding (calling super) using JavaScript (without Object.create)
var goog={};//inherits from closure library base
//http://docs.closure-library.googlecode.com/git/closure_goog_base.js.source.html#line1466
// with modifications for _super
goog.inherits = function(childCtor, parentCtor) {
function tempCtor() {};
tempCtor.prototype = parentCtor.prototype;
childCtor.prototype = new tempCtor();
childCtor.prototype.constructor = childCtor;
// modified _super
childCtor.prototype._super = parentCtor.prototype;
};
// Parent class dev
var Parent = function(){};
Parent.prototype.sayHi=function(){
console.log("hi from Parent");
}
// end class
// Child class dev
var Child = function(){}
goog.inherits(Child,Parent);
Child.prototype.sayHi=function(){
//_super only works on parent.prototype
//this is where functions are usually defined
//have to add this. to call _super as well
this._super.sayHi();
console.log("hi from Child");
}
// end Child
//code to test
var c = new Child();
c.sayHi();//hi from Parent and hi from Child
Even if you find a way to write helper functions and make JS constructor functions look like Java classes you have to understand prototype.
You can always try jOOP, though it does require jQuery.
https://github.com/KodingSykosis/jOOP
var myClass = $.cls({
main: function() {
$('body').append('My App is loaded <br/>');
}
});
var mySecondClass = $.cls({
main: function() {
this._super();
$('body').append('My Second App is loaded <br/>');
}
}, myClass);
var app = new mySecondClass();
http://jsfiddle.net/kodingsykosis/PrQWu/
I believe you are looking for more functionality than this, but if you want to just inherit a bunch of methods from another class you could do this
http://cdpn.io/Jqhpc
var Parent = function Parent () {
this.fname = 'Bob';
this.lname = 'Jones';
};
Parent.prototype.getFname = function getFname () {
return this.fname;
};
Parent.prototype.getLname = function getLname () {
return this.lname;
};
var Child = function Child () {
this.fname = 'Jim';
};
Child.prototype = Parent.prototype;
var child = new Child();
document.write(child.getFname()); //=> Jim
I've put these together with the help of others and several resources. I've made a fiddle of everything, and the stripped down code is posted below.
Basically I've learned how to use each of these patterns but I'm curious about the more fundamental differences between these approaches. Downstream code is practically identical with any of these patterns, but is there a reason why one should use one over another, beyond personal preference? Also though I've tried to gather up the most common patterns, please suggest your own if it's better.
Pattern 1 (Object Based):
var mouseDiff = {
"startPoint" : {"x" :0, "y" : 0},
"hypotenuse" : function(a,b) {
// do something
},
"init" : function(){
// do something
}
}
mouseDiff.init();
Pattern 2 (Most traditional as far as I know):
function MouseDiff() {
this.startPoint = {"x" :0, "y" : 0};
}
MouseDiff.prototype.hypotenuse = function(a,b) {
// do something
}
MouseDiff.prototype.init = function() {
// do something
}
var myMouse = new MouseDiff;
myMouse.init();
Pattern 3 (Making use of closure):
var MouseDiff2 = (function() {
var startPoint = {"x" :0, "y" : 0};
var hypotenuse = function(a,b) {
// do something
};
return {
hypotenuse: hypotenuse,
init : function(){
// do something
}
};
}());
MouseDiff2.init();
Pattern 1 is a singleton. If you only need one such object, it's just fine.
Pattern 2 builds new objects, and takes advantage of the prototype object so that when a new MouseDiff object is created, it will not create new copies of the functions (which are themselves data in JavaScript).
Pattern 3 requires more memory in comparison to a regular singleton but it offers static privacy.
I like the following pattern, as it covers various features, though it is really a combination of the constructor (pattern 2) and closure (pattern 3):
var MouseDiff = (function () {
var aStaticVariable = 'Woohoo!';
// And if you really need 100% truly private instance
// variables which are not methods and which can be
// shared between methods (and don't mind the rather
// big hassle they require), see
// http://brettz9.blogspot.com/search?q=relator
// (see also the new plans for a Map/WeakMap in ECMAScript)
function _APrivateStaticMethod () {
alert(aStaticVariable);
}
// An instance method meant to be called on the
// particular object as via ".call(this)" below
function _APrivateInstanceMethod () {
alert(this.startPoint.x);
}
// Begin Constructor
function MouseDiff() {
this.startPoint = {"x" :0, "y" : 0};
}
MouseDiff.prototype.hypotenuse = function(a,b) {
// do something
};
MouseDiff.prototype.init = function() {
// do something
_APrivateStaticMethod(); // alerts 'Woohoo!'
_APrivateInstanceMethod.call(this); // alerts 0 (but if not
// called with this, _APrivateInstanceMethod's internal
// "this" will refer (potentially dangerously) to the
// global object, as in the window in the browser unless
// this class was defined within 'strict' mode in which
// case "this" would be undefined)
};
return MouseDiff;
}());
var myMouse = new MouseDiff;
myMouse.init();
I do not know enough about JavaScript to tell you what if any performance differences exist between these approaches. Here are just two differences between these I noticed. I'm sure there are others.
Pattern 1 creates one object with those properties, including attached methods. Pattern 2 allows us to easily create many objects with the same methods attached, without rewriting them.
Pattern 3 is like a factory. Instead of relying on prototype to automatically attach these methods, the factory just creates them anew and returns the object. The usage of a closure allows us to hide the "member variables" of the object. There is no way to access startPoint or hypotenuse() except through the "public" interface returned.
Whenever I answer these types of theoretical JavaScript questions, I always fear there is some technical detail I am forgetting or overlooking. If so, let me know, and I will fix the answer.
Pattern two is my personally preference because it is the closest to traditional object oriented programming and allows for easy inheritance.
This post by John Resig (the guy behind JQuery) uses that method...
http://ejohn.org/blog/simple-javascript-inheritance/
[edit]
In fact, I don't think methods 1 or 3 have any benefits. 1 is, as someone else said, a singleton and does not allow multiple instances and 3... I don't know where to start with 3.
There is one more possible way to do this.
var MouseDiff = {};
(function(context) {
var privateVarialble = 0;
context.hypotenuse = function() {
//code here
};
context.int = function() {
//code here
}
})(MouseDiff);
Here we simply pass the namespace as an argument to a self-invoking function. The privateVarialble variable is private because it does not get assigned to the context.
We can even set the context to the global object (with a one word change!). Inside brackets (MouseDiff) make it (this). This is a big asset for library vendors – who can wrap their features in a self-invoking function and leave it to the user to decide whether they should be global or not.
http://www.jsoops.net/ is quite good for oop in Js. If provide private, protected, public variable and function, and also Inheritance feature. Example Code:
var ClassA = JsOops(function (pri, pro, pub)
{// pri = private, pro = protected, pub = public
pri.className = "I am A ";
this.init = function (var1)// constructor
{
pri.className += var1;
}
pub.getData = function ()
{
return "ClassA(Top=" + pro.getClassName() + ", This=" + pri.getClassName()
+ ", ID=" + pro.getClassId() + ")";
}
pri.getClassName = function () { return pri.className; }
pro.getClassName = function () { return pri.className; }
pro.getClassId = function () { return 1; }
});
var newA = new ClassA("Class");
//***Access public function
console.log(typeof (newA.getData));
// function
console.log(newA.getData());
// ClassA(Top=I am A Class, This=I am A Class, ID=1)
//***You can not access constructor, private and protected function
console.log(typeof (newA.init)); // undefined
console.log(typeof (newA.className)); // undefined
console.log(typeof (newA.pro)); // undefined
console.log(typeof (newA.getClassName)); // undefined
This has been answered elsewhere many times before but just to offer up some variety. ds.oop is a nice way to declare classes with constructors in javascript. It supports every possible type of inheritance (Including 1 type that even c# does not support) as well as Interfaces which is nice.
var Color = ds.make.class({
type: 'Color',
constructor: function (r,g,b) {
this.r = r; /* now r,g, and b are available to */
this.g = g; /* other methods in the Color class */
this.b = b;
}
});
var red = new Color(255,0,0); // using the new keyword to instantiate the class
Using jQuery, this is the format of most of the classes I write in JS:
$.Tabs = function(options){
var self = this;
this.defaults = {};
var cfg = $.extend(true, {}, this.defaults, options);
this.$elem = cfg.$elem;
function _init(){
var dontInit = false;
if (!cfg.$elem || !cfg.requiredProperty){
alert('missing params');
dontInit = true;
}
if (!dontInit){
self.$elem.bridge(self);
}
}
this.show = function(){};
this.hide = function(){};
_init();
}
The code above is just an example by the way.
My question is, how do you extrapolate common tasks/functionality from your classes, so every new class you write, you don't have to retype everything again?
I created a Class creation script based off of John Resig's Simple Javascript Inheritance pattern, which allows you to require certain parameters, bind event listeners for a pub/sub pattern, automatically combine defaults with options passed in, and it creates a bridge between the DOM element and the class instance (i.e $('elem').data('instanceNamespace', classInstance);)
But I'm uncomfortable with continuously using this class script to write my classes because it makes them less portable. But yet, I don't want all my classes to have so many similarities between them when it feels like those aspects can be abstracted.
Thoughts? Or how do you format your Javascript classes?
Thanks in advance.
Edit: Also, would anyone know the impact using a class creation script has on performance? I'm assuming the extra closures adds overhead but is it enough to make it not worthwhile to use?
I think the idea you are looking for is called a Mix-in.
Note: what follows is just vanilla javascript, no jQuery, but I think you'll see that prototype inheritance is very well suited to the idea of mixins.
Let's say you define a simple constructor:
var Person = function(name){
this.name=name;
this.sayhello = function(){
console.log(this.name + ' says hello');
};
};
Then we can mixin new abilities by copying the properties over to the new object with the function below:
var extend = function(destination, source) {
for (var property in source)
destination[property] = source[property];
return destination;
};
We can create some useful abilities that we may want to re-use for lots of different classes, so instead of having them all inherit from a common class, we can just mixin the new abilities at runtime:
var DanceMixin = {
dance: function(){
console.log(this.name + ' is dancing!');
}
};
var SingMixin = {
sing: function(){
console.log(this.name + ' is singing!');
}
};
var bob = new Person('bob');
extend(bob, SingMixin);
extend(bob, DanceMixin);
bob.sing();
/* bob is singing! */
bob.dance();
/* bob is dancing! */
bob.sayhello();
/* bob says hello */
Note that this is adding the new abilities to only a single object. If we wanted to add these abilities to all Person objects, we would need to modify the Person prototype.
Now let's say we have another trivial constructor for Animals:
var Animal = function(name){
this.name = name;
this.roar = function(){
console.log(this.name + ' is roaring!');
};
};
And let's say we want all of our animals to have the ability to dance. So we can add the DanceMixin to the Animal prototype using a function such as:
var mixin = function(dest, src){
for (var property in src)
dest.prototype[property] = src[property];
return dest;
}
mixin(Animal, DanceMixin);
Now we can make some animals that can all dance...
var lion = new Animal('lion');
lion.dance()
/* lion is dancing! */
By the way, I highly recommend you check out the MooTools approach to the problem, which is quite elegant. Here is an example of using Implements in MooTools classes to facilitate mixins.
In OO Javascript constructor pattern: neo-classical vs prototypal, I learned that constructors using prototypal inheritance can be 10x faster (or more) than constructors using the so-called neo-classical pattern with closures as proposed by Crockford in his "Good Parts" book and presentations.
For that reason it seems like preferring prototypal inheritance seems like the right thing, in general.
Question Is there a way to combine prototypal inheritance with the module pattern to allow private variables when necessary?
What I am thinking is:
// makeClass method - By John Resig (MIT Licensed)
function makeClass(){
return function(args){
if ( this instanceof arguments.callee ) {
if ( typeof this.init == "function" )
this.init.apply( this, args.callee ? args : arguments );
} else
return new arguments.callee( arguments );
};
}
// =======================================================
var User = makeClass();
// convention; define an init method and attach to the prototype
User.prototype.init = function(first, last){
this.name = first + " " + last;
};
User.prototype.doWork = function (a,b,c) {/* ... */ };
User.prototype.method2= (function (a,b,c) {
// this code is run once per class
return function(a,b,c) {
// this code gets run with each call into the method
var _v2 = 0;
function inc() {
_v2++;
}
var dummy = function(a,b,c) {
/* ... */
inc();
WScript.echo("doOtherWork(" + this.name + ") v2= " + _v2);
return _v2;
};
var x = dummy(a,b,c);
this.method2 = dummy; // replace self
return x;
};
})();
That isn't quite right. But it illustrates the point.
Is there a way to do this and is it worth it?
preferring prototypal inheritance seems like the right thing, in general
Well... it's the more natural, native-feeling thing to do in JavaScript, certainly. But so much JavaScript does is wrong that this isn't necessarily a compliment!
Certainly when performance isn't an issue, objects that get their own bound copies of each method are easier to cope with than objects that share their methods, because you can just pass on a reference to object.method without having to make a closure-delegate or function.bind.
Is there a way to combine prototypal inheritance with the module pattern to allow private variables when necessary?
What do you want from private variables? If it's some Java-style idea of security by encapsulation, I'd give that up and just do it the Python way: put an underline on the start of the member name and anyone who wants to use from the outside will be suitably warned that it's unsupported and may screw up. There is never a security boundary inside JavaScript code executing on the same page that would warrant keeping your privates really private.
If what you want is to avoid having to locate the right copy of this when the method is called, you could manually bind methods methods in the initialiser:
var Thing= makeClass();
Thing.prototype.init= function(a) {
this._a= a;
this.showA= this.showA.bind(this);
};
Thing.prototype.showA= function() {
alert(this._a);
};
thing= new Thing(3);
setTimeout(thing.showA, 1000); // will work as `thing` has its own bound copy of `showA`
(function.bind is future-JavaScript that you can hack into the Function.prototype now until browsers support it.)
This naturally loses some of the lightweight nature of prototype-based objects, but at least you can still have them share members that aren't methods, and methods that are never going to be used as delegates, as long as it's clear and you can always remember which methods are the ones that you can use this way.
If you simply want to be able to type a private variable name without having to put this. all the time then, yeah, you'd have to do it with a closure. Your example world maybe be a little clearer called from the initialiser rather than using the first-time-self-writing:
var User= makeClass();
User.prototype.init= function(first, last){
this.name= first+' '+last;
this.method2= this._method2factory();
};
User.prototype._method2factory= function() {
var _v2= 0;
function inc() {
_v2++;
}
return function method2(a,b,c) {
/* ... */
inc();
WScript.echo('doOtherWork('+this.name+') v2= '+_v2);
return _v2;
};
};
But I'm not really sure this gets you much in comparison to just writing this._v2 and this._inc().
I'm not totally sure I understand your question. But going from what I think I do understand...
function Foo () { /*constructor*/
var counter = 0; /* private variable */
this.incrementCounter=function () { /*privileged function */
counter++
}
this.getCounter=function () { /*privileged function */
return counter;
}
}
/*public functions. Note: this pattern destroys constructor property.
Lesson: Don't depend on the constructor property! */
Foo.prototype = {
toString: function () {
var string = "";
var count = this.getCounter();
while(count--) {
string+="*"
}
return string;
}
}
var bar = new Foo();
bar.incrementCounter();
bar.incrementCounter();
bar.toString(); /* in theory, this returns "**".. haven't tested code */
You may take a look at
https://github.com/riga/jclass
I think that's what you're looking for.
Personally, I prefer the following syntax :
var keyValueStore = (function() {
// Singleton private properties
var count = 0;
var kvs = function() {
// Instance private / privileged properties
count++;
};
kvs.prototype = {
// Instance public properties
'data' : {},
'get' : function(key) { return this.data[key]; },
'set' : function(key, value) { this.data[key] = value; },
'delete' : function(key) { delete this.data[key]; },
'getLength' : function() {
var l = 0;
for (p in this.data) l++;
return l;
}
};
return {
// Singleton public properties
'create' : function() { return new kvs(); },
'count' : function() { return count; }
};
})();
With this syntax, you have a singleton object, the possibility to create instances with prototype inheritance and the possibility to define private properties at several levels.
You use it like this :
kvs = keyValueStore.create();
kvs.set('Tom', "Baker");
kvs.set('Daisy', "Hostess");
var profession_of_daisy = kvs.get('Daisy');
kvs.delete('Daisy');
console.log(keyValueStore.count());