I have the following code that creates two objects (ProfileManager and EmployerManager) where the object EmployerManager is supposed to inherit from the object ProfileManager.
However, when I do alert(pm instanceof ProfileManager); it returns false.
function ProfileFactory(profileType) {
switch(profileType)
{
case 'employer':
return new EmployerManager();
break;
}
}
function ProfileManager() {
this.headerHTML = null;
this.contentHTML = null;
this.importantHTML = null;
this.controller = null;
this.actions = new Array();
this.anchors = new Array();
}
ProfileManager.prototype.loadData = function(action, dao_id, toggleBack) {
var step = this.actions.indexOf(action);
var prv_div = $('div_' + step - 1);
var nxt_div = $('div_' + step);
new Ajax.Request(this.controller, {
method: 'get',
parameters: {action : this.actions[step], dao_id : dao_id},
onSuccess: function(data) {
nxt_div.innerHTML = data.responseText;
if(step != 1 && !prv_div.empty()) {
prv_div.SlideUp();
}
nxt_div.SlideDown();
for(i = 1; i <= step; i++)
{
if($('step_anchor_' + i).innerHTML.empty())
{
$('step_anchor_' + i).innerHTML = this.anchors[i];
}
}
}
}
)
}
EmployerManager.prototype.superclass = ProfileManager;
function EmployerManager() {
this.superclass();
this.controller = 'eprofile.php';
this.anchors[1] = 'Industries';
this.anchors[2] = 'Employer Profiles';
this.anchors[3] = 'Employer Profile';
this.actions[1] = 'index';
this.actions[2] = 'employer_list';
this.actions[3] = 'employer_display';
}
var pm = new ProfileFactory('employer');
alert(pm instanceof ProfileManager);
BTW, this is my very first attempt at Object-Oriented JavaScript, so if you feel compelled to comment on the stupidity of my approach please feel free to do so, but offer suggestions on how to approach the problem better.
I've been using something similar to Dean Edward's Base.js model.
http://dean.edwards.name/weblog/2006/03/base/
Prototype supports (mimicing) class inheritance via the Object.extend() function.
However, it could be argued that trying to impose class-based inheritance on a language which doesn't support classes is an example of "when you only have a hammer, the whole world looks like a nail".
Thanks for all of the comments. However, the solution to the problem was found in making this change to the declaration of the EmployerManager:
function EmployerManager() {
this.controller = 'eprofile.php';
this.anchors = new Array('Industries', 'Employer Profiles', 'Employer Profile');
this.actions = new Array('index', 'employer_list', 'employer_display');
}
EmployerManager.prototype = new ProfileManager;
Apparently JavaScript supports two different types of inheritance, function based and prototype based. The function based version is what I originally posted but could not make work because the EmployerManager could not see the loadData method that was part of ProfileManager's prototype.
This new example is prototype based and works now. EmployerManager is now an instance of ProfileManager.
In your code, pm is an instance of EmployerManager that has a superclass of ProfileManager. That seems backwards to me. Shouldn't ProfileManager have a superclass of EmployerManager?
I just wanted to interject that while JavaScript is an object oriented language, it does not have many of the features common in other popular OO languages. Conversely, it also has many features that other popular OO languages do not.
As you have already discovered inheritance is managed via prototype objects, rather than by class inheritance. However, the prototype object is not examined when using the "instanceof" operator. This means that JavaScript does not support polymorphism. At least not out of the box.
You can find libraries that will make JavaScript conform to the model of OOP that you're used to; if you're under the gun this might be the best solution. (Although no library is ever going to make a JavaScript object polymorphic when examined using "instanceof"; an isInstanceOf function would probably be necessary.) Or you could choose another language which does conform to that model of OOP, but you're probably working in a browser, so that's obviously not an option. Or you could answer the question, "how can I solve my problem without polymorphism?"
You should note that the same question has been asked (by me). Check out the answers on that post.
You can use new or Object.create to achieve classical inheritance
function A(){
B.call(this);
}
function B(){
}
//there are 2 ways to make instanceof works
//1. use Object.create
A.prototype = Object.create(B.prototype);
//2. use new
//A.prototype = new B();
console.log(new A() instanceof B); //true
//make instanceof works
EmployerManager.prototype = Object.create(ProfileManager.prototype);
//add other prototype memebers
EmployerManager.prototype.superclass = ProfileManager;
console.log(new EmployerManager() instanceof ProfileManager); //true
Related
I'm Studying Kyle Simpson's YDKJS: this and the object prototype, and I'm trying to figure for myself if using Object.create() is really more efficient in behavior delegation in linked objects than the operator this I have copied Kyle's example code (in the code snippet), and I am asking you to help me to refactor it to use the new keyword (or using ES6 class) if it's possible. It's just hard for me to take things for granted :)
var Task = {
setID: function(ID) {this.id = ID;},
outputID(){console.log(this.id);}
};
var XYZ = Object.create(Task);
XYZ.prepareTask = function(ID, Label){
this.setID(ID);
this.label = Label;
};
XYZ.outputTaskDetails = function(){
this.outputID();
console.log(this.label)
}
var myTask = Object.create(XYZ);
myTask.prepareTask("myID","Some Task");
myTask.outputTaskDetails()
console.log(myTask)
I have picked up a piece of software which is fairly old and it has this form of "class" definition
function thisThing(parm1, parm2)
{
var self = new BaseThing(parm1);
self.val2 = parm2;
self.function2 = function() { ... }
return self;
}
I'd like to convert the whole hierachy to use the thisThing.prototype style of class, something like this
function thisThing(parm1, parm2)
{
var self = new BaseThing(parm1);
self.val2 = parm2;
return self;
}
thisThing.prototype = Object.create(BaseThing.prototype);
thisThing.prototype.constructor = thisThing;
thisThing.prototype = {
function2() { ... }
}
but I'm not sure if it is safe to mix the two styles.
Do I have to convert the whole hierarchy at once? Or can I do it a class at a time, and in which case do I need to do it top up, bottom down, or can I do it in the order I come across classes?
A note: Please don't suggest using ES6 classes, as they are not available in my current environment.
You've said that the old thisThing is called via new, which is good news in terms of whether you can mix things together (although we could work around it if not).
What you've shown as your desired form is quite non-standard, and thisThing.prototype is never used in it. I'm going to assume you mean you want to use standard constructor functions, which look like this:
function ThisThing(parm1, parm2) {
BaseThing.call(this, parm1);
this.parm2 = parm2;
}
ThisThing.prototype = Object.create(BaseThing.prototype);
ThisThing.prototype.constructor = ThisThing;
ThisThing.prototype.someMethod = function() {
// ...
};
Based on what you have in the question, you can go ahead and do that. (I do recommend the change in capitalization, it's the overwhelming standard for constructor functions.)
If there's any chance code might be calling it without new, you can make it tolerate that by detecting what's happened and handing off to new in the constructor:
function ThisThing(parm1, parm2) {
if (!(this instanceof ThisThing)) {
// Called without `new`; handle it
return new ThisThing(parm1, parm2);
}
BaseThing.call(this, parm1);
this.parm2 = parm2;
}
// ...
The thisThing you showed was using BaseThing as a constructor, so I assume (from that and the name) that it's already using the constructor pattern above.
You should be able to replace it like this. The only issue might be setting the param1 is a new BaseThing, so you might need to modify your old code.
by doing this you are using prototypical inheritance to get the methods of BaseThing.
Conversion like this can be mixed with your existing code with no problems so you can change one class at a time.
function ThisThing(param1, param2) {
this.val1 = param1
this.val2 = param2
}
ThisThing.prototype = new BaseThing
ThisThing.prototype.function2 = function() {}
var thing = new ThisThing(1, 2)
console.log(
thing instanceof BaseThing, // => true
thing instanceof ThisThing // => true
)
In JavaScript there's a pattern to achieve inheritance called "Functional inheritance" described in chapter 5 of Crockfords "JavaScript: the good parts".
One of the disadvantages of the pattern -- as compared to using the pseudo-classical pattern -- is that we lose the ability to distinguish types using the instanceof operator.
Is there any way to achieve the same goal? How can we know that two objects are somehow related because they are of the same parent/base "type"?
Also how can we tell even though they are descendants of the same type they are different types themselves?
I don't know if not being able to use instanceof is a big loss but it doesn't seem like it is.
Notes
For those who are not familiar with Crockford's explanation, you can see an example at: JSFiddle, taken from here.
The instanceof operator is not special. You can implement it yourself as explained on the Mozilla Developer Network. See the accepted answer to the following question for more details:
JavaScript inheritance and the constructor property
Here's how the instanceof operator can be implemented in JavaScript:
function instanceOf(object, constructor) {
while (object != null) {
if (object == constructor.prototype) { //object is instanceof constructor
return true;
} else if (typeof object == 'xml') { //workaround for XML objects
return constructor.prototype == XML.prototype;
}
object = object.__proto__; //traverse the prototype chain
}
return false; //object is not instanceof constructor
}
Want to implement instanceOf for functional inheritance? That's easy to do too:
var object = child({ name: "a functional object" });
alert(object.instanceOf(child)); // true
alert(object.instanceOf(base)); // true
alert(object.sayHello()); // Hello, I'm a functional object
function base(spec) {
var that = {};
that.name = spec.name;
that.constructors = [base];
that.instanceOf = instanceOf;
return that;
}
function child(spec) {
var that = base(spec);
that.sayHello = sayHello;
that.constructors.push(child);
return that;
function sayHello() {
return "Hello, I'm " + this.name;
}
}
function instanceOf(constructor) {
return this.constructors.indexOf(constructor) >= 0;
}
Of course, in real functional programming there's no need to use instanceof at all.
So imagine we have these:
mammal { giveBirth }
reptile { layEgg }
cat : mammal { purr, playWithChildren }
dog : mammal { bark }
lion : mammal { purr }
(cat inherits mammal and implements purr() etc...)
Now imagine you have an array of animals.
What I think you're asking is how do we tell if animals[0] is a cat.
The desire to know if animals[0] is a cat comes from the fact we know that cats can do certain things. Instead of knowing if animals[0] is a cat what we really want to know is can animals[0] purr. Perhaps animals[0].purr !== undefined is more accurate than knowing if it is a cat. This does mean that we need to check for each of the functions rather than the container concept of a cat which we know implements several functions but it makes the implementation more robust and future proof (consider if we only cared about purring and lions were added to the types of animals later).
As for the question about inheritance again I would suggest that we don't need to know if the animal is a mammal we need to know if they giveBirth. This would again ensure that our implementation is more future proof so that when we add marsupial later all of our logic around giving birth rather than laying an egg still stands.
Store a parent object in the object, then
if (obj1.parentObject == obj2.parentObject) {//Do your things}
There are no certain types and distinction though inctanceof in "Functional inheritance"("JavaScript: the good parts"). It's about an exchange and relation between anonymous functions, which are generating objects, usually, with a private functionality. The logical hierarchy of those function is set with conditional preference. That functions can call each other, extend "parent" object methods, expand its functionality.
For example, in "functional inheritance" creating a new type, which is called "Mammal", would look like:
var mammal = function (spec) {
var that = {};
that.get_.name = function () {
return spec.name;
};
that.says = function () {
return spec.saying || '';
};
return that;
};
var myMammal = mammal({name: 'Herb'});
By some conditional agreements we can accept it as a parent type(class).
Now we can create another anonymous function that will be responsible for subtype(subclass) of "Mammal" type(class). This function will call "parent" function mammal() to get the object with basic functionality:
var cat = function (spec) {
spec.saying = spec.saying || 'meow';
var that = mammal(spec);
that.purr = function (n) {
var i, s = '';
for (i = 9; i < n; i += 1) {
if (s) {
s +=
}
s += 'r';
}
return s;
};
that.get_name = function () {
return that.says() + ' ' + spec.name + ' ' + that.says();
};
return that;
};
var myCat = cat({name: 'Henrietta'});
I am new to javascript. As far as I can tell there are 5 ways to make an object (really a struct I guess). I was wondering what the best way is. Thanks.
var makeOption = function(name, dataType){
var option = {
name: name,
dataType: dataType
};
return option;
};
var makeOption2 = function(name, dataType){
this.name = name;
this.dataType = dataType;
};
function makeOption3(name, dataType){
this.name = name;
this.dataType = dataType;
};
var makeOption4 = function makeOption4Name(name, dataType){
this.name = name;
this.dataType = dataType;
};
var v1A = makeOption("hannah", "int");
var v1B = new makeOption("hannah", "int");
//var v2A = makeOption2("hannah", "int"); <- undefined.
var v2B = new makeOption2("hannah", "int");
// var v3A = makeOption3("hannah", "int"); <- undefined.
var v3B = new makeOption3("hannah", "int");
// var v4A = makeOption4("hannah" ,"int"); <- undefined.
var v4B = new makeOption4("hannah" ,"int");
This is what is displayed in the firebug DOM Tab:
I'd go with #3.
#1 does not allow the use of prototype.
#2 is anonymous, and anonymous functions don't help in debugging because you don't see what function is causing problems if it is (the variable name the function is stored is not part of the function, whereas the function's name is).
#4 is confusing - two possibilities to access one function.
Whole chapters of books on JavaScript best practices have been written on this subject. That said: If you aren't concerned about inheritance and aren't going to be creating numerous copies of an object with methods, i.e., you are just creating a "struct", then object literal notation, your first example, is the way to go. In that approach, you are using object literal notation, which is lightweight and fast. It doesn't mess with the object prototype or require the use of the new operator.
Start adding methods to your object, however, and the answer changes to "it depends."
By the way, you left out a couple of ways to create an object:
var o = {};
o.name = "hannah";
o.dataType = "int";
and, not recommended:
var o = new Object();
o.name = "hannah";
o.dataType = "int";
The first one is preferable from design standpoint - based on your name.
makeOption implies that it creates and retuens an object.
All your other solutions do NOT actually return an object and require "new" call. They may have similar/identical technical results when used as pure data structures, but only the first one works as a "object maker", as its name implies.
If you want to use #2/3 (#4 makes no sense - why would you clone the function twice), then you need to name it something else - optionPrototype may be.
I personally use makeoption3 I have tried them all and found that makeoption3 is the cleanest and simplest if you are writing multiple objects. Also it has less code than the others keeping your file size down.
function makeOption3(name, dataType){
this.name = name;
this.dataType = dataType;
};
If you don't need inheritance capabilities, just go with #1 (as you're essentially just using it to build and return an object literal). Otherwise I'd go with #3, as it allows for protoype methods and is also a named function rather than an anonymous one.
Taking this from a Post John Resig made about javascript "Class" instatiation, he points out...
// Very fast
function User(){}
User.prototype = { /* Lots of properties ... */ };
// Very slow
function User(){
return { /* Lots of properties */ };
}
which is what we're talking about he posted this snippet of code...
// makeClass - 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 );
};
}
And then using it, leveraging the speed of using the prototype chain..
var User = makeClass();
User.prototype.init = function(first, last){
this.name = first + " " + last;
};
var user = User("John", "Resig");
user.name
// => "John Resig"
This also takes care of the usage of new it allows the use of the keyword, but doesn't require it.
Link to Original Post
Why don't you want to use object literals? It seems like you're really asking about objects and inheritance..?
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 9 years ago.
I'm sick of seeing dozens of different ways of doing object oriented programming in Javascript. Can anyone just tell me which technique I should use considering I want to work on a large scale project and I want my code to be future proof?
These are just a few quick guidelines I've come up with, if anyone else has anything meaningful to add, I've set this answer as a community wiki so it should be easy enough for you to edit.
Namespace your objects to ensure they will never conflict with third party JavaScript libraries.
window['Andrew']['JS'] = {
addEvent: function(el,evName) {/*Stuff*/},
Rectangle: function(width,height) {/*Stuff*/}
};
So then you would create a rectangle object by using:
var myRect = new Andrew.JS.Rectangle(14,11);
And then your code will never interfere with, or be interfered by anybody else's Rectangle.
Use a consistent naming strategy, specifically:
Object names should be capitalized, everything else (variables, functions) should begin with a lower case character i.e.
var myRect = new Andrew.JS.Rectangle(14,11);
document.write(myRect.getArea());
Ensure everything is meaningful, i.e. verbs for methods, nouns + adjectives for parameters.
Make sure all methods and parameters are relevant to the object they belong to. e.g.
In this example, the area of the rectangle can be converted to square feet using the method inSquareFeet().
myRect.getAreaObject().inSquareFeet();
Make sure inSquareFeet is a method of the object returned by getAreaObject() and not a method of Andrew.JS.Rectangle
Use constructors, or more specifically, try as hard as possible to make sure that an object doesn't need any further initialization to be used once it has been constructed, so instead of:
var Person = function()
{
this.name = "";
this.sayHello = function ()
{
alert(this.name + " says 'Hello!'");
return this;
}
}
var bob = new Person();
bob.name = "Bob Poulton";
bob.sayHello();
try:
var Person = function(name)
{
this.name = name;
this.sayHello = function ()
{
alert(this.name + " says 'Hello!'");
return this;
}
}
var bob = new Person("Bob Poulton");
bob.sayHello();
I always use John resig's:
http://ejohn.org/blog/simple-javascript-inheritance/
It's simple and doesn't require any frameworks to function.
Because you are working on a large scale project i would suggestion a javascript framework like mootools http://mootools.net/.
It has a good class and inheritance structure.
My ideal Object for OOP is like using an Instance method with prototypes:
Example:
var Users = function()
{
var _instance;
this.prototype.getUsername = function(){/*...*/}
this.prototype.getFirstname = function(){/*...*/}
this.prototype.getSecurityHash = function(){/*...*/}
/*...*/
/*Static Methods as such*/
return { /*Return a small Object*/
GetInstance : function()
{
if(_instance == null)
{
_instnance = new Users(arguments);
}
return _instnance; //Return the object
},
New: function()
{
_instnance = null; //unset It
return this.GetInstnace(arguments);
}
}
}
Then I would always use like:
Firstname = Users.GetInstance('Robert','Pitt').getFirstname();
Username = Users.GetInstance().getUsername(); //Returns the above object.
Me = Users.New('Robert',null); //Deletes the above object and creates a new instance.
Father = Users.New('Peter','Piper'); //New Object
Me.AddFather(Father); //Me Object.
And that's the kind of road i go down when it comes to building a JavaScript OO Style architecture.
just for your information, i think YUI provides few great tutorials on this topic
//Create and define Global NameSpace Object
( function(GlobalObject, $, undefined)
{
GlobalObject.Method = function()
{
///<summary></summary>
}
GlobalObject.Functionality = {};
}) (GlobalObject = GlobalObject || {}, jQuery);
//New object for specific functionality
( function(Events, $, undefined)
{
//Member Variables
var Variable; // (Used for) , (type)
// Initialize
Events.Init = function()
{
///<summary></summary>
}
// public method
Events.PublicMethod = function(oParam)
{
///<summary></summary>
///<param type=""></param>
}
// protected method (typically define in global object, but can be made available from here)
GlobalObject.Functionality.ProtectedMethod = function()
{
///<summary></summary>
}
// internal method (typically define in global object, but can be made available from here)
GlobalObject.InternalMethod = function()
{
///<summary></summary>
}
// private method
var privateMethod = function()
{
///<summary></summary>
}
}) (GlobalObject.Funcitonality.Events = GlobalObject.Funcitonality.Events || {}, jQuery )
// Reusable "class" object
var oMultiInstanceClass = function()
{
// Memeber Variables again
var oMember = null; //
// Public method
this.Init = function(oParam)
{
oMember = oParam;
for ( n = 1; i < oMemeber.length; i += 1 )
{
new this.SubClass.Init(oMember[i]); // you get the point, yeah?
}
}
this.Subclass = function()
{
this.Init = function() { }
}
}
The strength to this is that it initializes the Global object automatically, allows you to maintain the integrity of your code, and organizes each piece of functionality into a specific grouping by your definition.
This structure is solid, presenting all of the basic syntactical things you would expect from OOP without the key words.
There are even some ingenious ways to set up interfaces as well. If you choose to go that far, a simple search will give you some good tutorials and tips.
Even setting up intellisense is possible with javascript and visual studio, and then defining each piece and referencing them makes writing javascript cleaner and more manageable.
Using these three methods as needed by your situation helps keep the global namespace clean, keep your code organized and maintains separation of concerns for each object.. if used correctly. Remember, Object Oriented Design is of no use if you don't utilize the logic behind using objects!
function foo() {
var bar = function() { console.log("i'm a private method"); return 1; };
var iAmAPrivateVariable = 1;
return {
publicMethod: function() { alert(iAmAPrivateVariable); },
publicVariable: bar()
}
}
//usage
var thing = foo()
This is a functional approach, and has a great deal more going for it (such as encapsulation) then anything else you are going to see
In a general way, you shouldn't be doing OO in javascript, it isn't that great a language for it for a great many reasons. Think scheme with squiggly brackets and semi-colons, and you will start writing the language like the pros do. That being said, sometime OO is a better fit. In those cases, the above is typically the best bet
to bring inheritance into the mix
function parent() {
return { parentVariable: 2 };
}
function foo() {
var bar = function() { console.log("i'm a private method"); return 1; };
var iAmAPrivateVariable = 1;
me = parent();
me.publicMethod = function() { alert(iAmAPrivateVariable); };
me.publicVariable = bar();
return me;
}
This makes things a tad more complected, but accomplishes the desired end result while still taking a functional approach to OO concepts (in this case, using decorator functions instead of real inheritance). What I like about the whole approach is we are still really treating objects the way they are intended to be in this kind of language -- a property bag you can attach stuff to at will.
Another note is this is wildly different then what you will see most of the time in most of the jobs you will ever work at, and often is very hard to explain a) what is going on, and b) why it is a good idea to coworkers.
I use such a pattern and recommend to you to use it too:
function Person(firstname, lastname, age)
{
var self = this;
var _ = {};
// Private members.
var firstname = firstname;
var lastname = lastname;
var age = age || 'unknown';
// Private methods.
function first_letter_to_uppercase(str) {
return str.charAt(0).toUpperCase() + str.substr(1);
}
// Public members and methods.
_.get_age = function()
{
return age;
}
_.get_name = function()
{
return first_letter_to_uppercase(firstname) + ' ' +
first_letter_to_uppercase(lastname);
}
return _;
}
var p = new Person('vasya', 'pupkin', 23);
alert("It's " + p.get_name() + ', he is ' + p.get_age() + ' years old.')
You can try with a simple, usefull and quick object:
var foo = {
foo1: null,
foo2: true,
foo3: 24,
foo4: new Array(),
nameOfFunction1: function(){
alert("foo1");
},
nameOfFunction2: function(){
alert("foo2");
},
}
To use this, you have to create an instance of this object and use like a object in java:
foo.nameOfFunction2();
Also you can check this link to other solution: http://www.javascriptkit.com/javatutors/oopjs.shtml
I hope that answer your question.