I normally in my project create my class in this way... Object literal.
var objectName = {
//global variables
a : 'somevalue',
func1: function(){
},
func2: function(){
}
}
If i have to turn this into prototype format, how would I do that?
What would be my advantage of using prototype than this one, when the job is getting done with this format.
Why do people speak so much on prototype.
Turned into a prototype would look something like:
var someObject = function() {
this.a = "somevalue";
};
someObject.prototype.func1 = function() { // work };
someObject.prototype.func2 = function() { // work };
var myObject = new someObject();
What are some advantages? Well, there are a bunch, but there
are a handful really practical reasons when prototypes make
more sense than object literals.
First is reduction of duplicated code; So, lets say you wanted
another object very smiliar to objectName, but you wanted a to
be a different value. You would probably end up with something like:
var objectName = {
a : 'somevalue',
func1: function(){ },
func2: function(){ }
}
var otherObjectName = {
a : 'otherValue',
func1: function(){ },
func2: function(){ }
}
And you could reduce the duplicated functions by saying
var objectName = {
a : 'somevalue',
func1: function(){ },
func2: function(){ }
}
var otherObjectName = {
a : 'otherValue',
func1: objectName.func1,
func2: objectName.func2
}
Or, using a prototype, I could just make it so I could pass in the value I want for a in during the construction of the object. The refactored code would look something like this:
var someObject = function(a) {
this.a = a;
};
someObject.prototype.func1 = function() { /* work */ };
someObject.prototype.func2 = function() { /* work */ };
var myObject = new someObject("somevalue");
var myOtherObject = new someObject("otherValue");
Now, if i wanted to add a new function to both of them. Using the object literal apporach, then you would have to remember to also add it to otherObjectName. As the number of your literals increased, it would take longer and more difficult to manage them all.
Using the prototype approach, all we would have to say is:
someObject.prototype.func3 = function() { // do even more work }
or even more interesting i could dynamically extend both object by only
having a reference to one by saying.
// find what function made me, get its prototype, and add a new function to it
myObject.constructor.prototype.func3 = function() { /* work */ }
myOtherObject.func3() // tada magic!
or I could make a new object, by only knowing a reference. like:
var newObject = myObject.constructor(myObject.a + " new");
Because both myObject and myOtherObject share the same constructor and prototype, there are a lot of interesting things
you can do with that relationship that you can't do with object literals.
You can think of prototypes as little factories to create objects
rather than having to create every object yourself as a literal.
Now, if you are thinking, "Well, I'm only going to have one
of these and I'm not going to be doing any of your crazy method
extending magic." Then defining an object literals is a perfectly valid apporach
for some problems. Sometimes using a prototype is better. Use the
pattern that makes sense for the problem that you are trying to solve,
rather than trying to fit your problem into a pattern.
Related
Somewhat of a JS newbie still, I'm trying to understand the best / cleanest way to use prototypes and inheritance.
Normally I write object/prototype definitions like this:
var Foo = function(data) {
this.data = data;
};
Foo.prototype = {
someMethod: function() {
return "whatever";
}
};
I like this because I often am using namespace objects a few layers deep, so it might actually look more like this:
App.Model.FooModel = function(){...};
App.Model.FooModel.prototype = {...};
This is nice because I don't have to type out the full name of every method to write the prototype, just the name, ie. someMethod: function(){} instead of App.Model.FooModel.prototype.someMethod = function(){}.
Now, the problem I've run into is I'm not sure how to do this with inheritance in JS. I can get inheritance working fine if I do it like this:
var Child = function(){...};
Child.prototype = new Parent;
Child.prototype.someMethod = function(){...};
...but now in a more complicated application we're back to writing out the full name of the object for every method, which I find both tedious and hard to read.
So, my question is: is there a clean, straightforward way to write prototypes that inherit from another object, except to attach all child methods using the full name of the object?
Thanks!
Well, this being javascript, you can always write your own:
function construct ( parent, fn, attr ) {
fn.prototype = new parent();
for (var x in attr) {
fn.prototype[x] = attr[x];
}
return fn;
}
You can do the hasOwnProperty check if you want but the above is simplest implementation for clarity. This function encapsulates the three steps into one. You can now simply do:
var Foo = construct(
Parent,
function(data) {
this.data = data;
},
{
someMethod: function() {
return "whatever";
}
}
);
If you don't like the syntax you can always come up with a better one. An alternative implementation is to simply implement the attr extension part and do the inheritance normally:
function extend (obj, attr) {
for (var x in attr) {
obj.prototype[x] = attr[x];
}
return obj;
}
Again, simplified for clarity. So the syntax now becomes:
var Foo = function(){...};
Foo.prototype = new Parent;
extend(Foo.prototype,{
someMethod : function(){...}
});
What is the best design pattern for achieving the following (which doesn't work)?
var obj = (function() {
// code defining private variables and methods
var _obj = {
property: value,
method1: function() {
// do stuff
},
method2: function() {
// use property
var prop = _obj.property; // obviously doesn't work
// call method1
obj.method1(); // "obj" not finished being defined yet!
}
};
// obviously now I could do...
var prop = _obj.property;
return _obj;
})();
// and I could now do...
obj.method1();
A variation which I think should work is
var obj = (function() {
var property = value,
method1 = function() {
// do stuff
},
method2 = function() {
// use property
var prop = property;
// call method1
method1();
},
_obj = {
property: property,
method1: method1,
method2: method2
};
return _obj;
})();
Similarly, how does it work for objects meant to be created with the new operator? Within the constructor function itself you can write this.method(). But what if you want to keep the constructor small, only defining those things which will likely be customized upon creation, and then defining the rest in the prototype? (This seems to be the common pattern.) Can the properties / methods within the prototype interact in any way?
var MyObj = function(name) {
this.name = name;
};
var obj = new MyObj('Bob');
MyObj.prototype = {
called_often: function() {
// lots more code than just the following
return document.getElementById('someID').value;
},
global_default: 'value', // can be changed, so need to pull value when run
does_stuff: function(value) {
var str = global_default + value, // can't access global_default on its own
input = MyObj.called_often(), // doesn't work; MyObj.prototype.called_often() DOES
name = this.name; // 'this' used in the prototype doesn't work
// even within a created object
return name + input + str;
}
};
I'm sure there's better ways to achieve my result whenever I run into this problem. This code isn't situation specific and just illustrates the general problem. So you won't be able to give me an alternative for those specific situations I run into. But maybe you can help my overall thinking.
Well, from your first example:
var _obj = {
property: value,
method1: function() {
// do stuff
},
method2: function() {
// use property
var prop = this.property;
// call method1
this.method1();
}
};
That's what the this value is for.
Now, what you cannot do is refer to a property of an "under construction" object from elsewhere in the object literal syntax. (It's hard to give an example because it's just not syntactically possible.) In cases where you want to do that, you do need one or more separate assignment statements.
Guess what? You are making simple stuff complex. Pointy's answer is good, but the prototype way is better for several reasons. That's why I am describing (rather, making corrections in) the last method. Check this fiddle.
var MyObj = function(name) {
this.name = name;
};
MyObj.prototype = {
called_often: function() {
// lots more code than just the following
return 'VALUE'; //document.getElementById('someID').value;
},
global_default: 'value', // can be changed, so need to pull value when run
does_stuff: function(value) {
var str = this.global_default + value, // can't access global_default on its own
input = this.called_often(), // doesn't work; MyObj.prototype.called_often() DOES
name = this.name; // 'this' used in the prototype doesn't work
// even within a created object
return name + input + str;
}
};
var obj = new MyObj('Bob');
I'm designing an OOP inheritance pattern for many applications I'm building. Javascript has many ways of doing this, but I stumbled on a pattern I really like. But now I'm struggling with the need for a separation of classes and instances.
I have a base object called Root. And it has a main method called inherit. To create a new object you use
var Person = Root.inherit({
name : "",
height : 0,
walk : function() {},
talk : function() {}
});
Then to create an "instance" you would
var sally = Person.inherit({
name : "sally",
height : "5'6"
});
sally can .talk() and she can walk() and she has a .name and a .height
You can make more people the same way.
If you want a constructor you use
var Person = Root.inherit({
_construct : function() {
// do things when this object is inherited from
},
name : "",
height : 0,
walk : function() {},
talk : function() {}
});
It also has the ability to have init, when the object is first defined in code (singletons use this)
var Person = Root.inherit({
_init : function() {
// called at runtime, NOT called if an object is inherited from me
},
name : "",
height : 0,
walk : function() {},
talk : function() {}
});
So as you can see, everything uses .inhert(). There are no classes and no instances really. Everything is an instance of something. The only real problem I found so far is that there is no concept of "type", but you can always just check for a method if you need to. Also you can't protect a 'class', as a 'class' can be changed during execution if the developer accidentally changed it, or meant to change it.
So my question is: Is there a need in javascript to have an explicitly and controlled separation of class structure and instances of the class? Are there any issues with treating every object as an instance?
No there's no need since Javascript is a Prototypal based language, meaning that classes are not involved. You are just creating clones of the objects.
http://en.wikipedia.org/wiki/Prototype-based_programming
As far as the concept of type, the type is object.
A good read for more info about this would be Javascript Patterns by Stoyan Stefanov he has several different creational patterns that address your concerns, including examples that implement Design Patterns from the gang of four's design patterns.
http://www.amazon.com/JavaScript-Patterns-Stoyan-Stefanov/dp/0596806752
So my question is: Is there a need in javascript to have an explicitly and controlled separation of class structure and instances of the class? Are there any issues with treating every object as an instance?
Not really, if you're happy with it, it's fine.
The more normal form of JavaScript inheritance does much the same thing. You'll frequently see structures like this (severely cut down for brevity):
function Base() {
}
Base.prototype.foo = function() {
};
function Derived() {
}
Derived.prototype = new Base();
...and of course, new Base() is also how you create instances of Base. So your system is quite similar.
Again, the above is a sketch, not a full example. For one thing, usually you'd see construction and initialization separated out, so you don't literally see Derived.prototype = new Base() so much as something that creates an object with Base's prototype but without actually calling Base (which Derived would do later), but you get the idea. Granted that statement somewhat weakens the similarity with your system, but I don't think it breaks it at all.
At the end of the day, it's all about objects (instances), which are either used directly (your sally) or indirectly by providing features to other objects (Person, Root) by cloning or by setting them up as the prototype of the other object.
Javascript's inheritance is prototypical which means everything object is an instance. You actually have to do extra work to get the classical inheritance.
This is how I work in javascript
// this is class
function person(){
// data is member variable
this.name = null;
this.id = null;
//member functions
this.set_name = _set_name;
this.get_name = _get_name;
this.set_id = _set_id;
this.get_id = _get_id;
function _set_name(name){
this.name = name;
}
function _get_name(name){
return this.name;
}
function _set_id(id){
this.id = id;
}
function _get_id(id){
return this.id;
}
}
// this is instance
var yogs = new person();
yogs.set_id(13);
yogs.set_name("yogs");
hope it may help
Start with some basic object...
// javascript prototypes - callback example - javascript objects
function myDummyObject () {
that = this;
} // end function myDummyObject ()
// begin dummy object's prototype
myDummyObject.prototype = {
that : this,
// add a simple command to our dummy object and load it with a callback entry
say : function () {
var that = this;
console.log('speaking:');
that.cb.run("doSay");
}
} // end myDummyObject proto
extend with a sub prototype..
// here we addon the callback handler... universally self sufficient object
var cb = {
that : this, // come to papa ( a link to parent object [ myDummyObject ] )
jCallback : new Array(new Array()), // initialize a javascript 2d array
jCallbackID : -1, // stores the last callback id
add: function(targetFnc, newFunc) {
var that = this;
var whichID = that.jCallbackID++;
// target, addon, active
that.jCallback[that.jCallback.length] = { 'targetFunc' : targetFnc, 'newFunc' : newFunc, 'active' : true, 'id': whichID };
return whichID; // if we want to delete this later...
}, // end add
run: function(targetFnc) {
var that = this;
for(i=0;i <= that.jCallback.length - 1;i++) // go through callback list
if( that.jCallback[i]['targetFunc'] == targetFnc && that.jCallback[i]['active'] == true )
that.jCallback[i]['newFunc'](); // run callback.
}, // end run
remove: function (whichID) {
var that = this;
console.log('removing:' + whichID);
for(i=0;i <= that.jCallback.length - 1;i++) // go through callback list
if( that.jCallback[i]['id'] == whichID )
that.jCallback[i]['newFunc'](); // run callback.
} // end remove
}
// add the object to the dummy object...
myDummyObject.prototype.cb = cb;
Example:
var testing = new myDummyObject();
testing.cb.add('doSay', function () { console.log('test: 213123123'); } );
// test remove...
var testid = testing.cb.add('doSay', function () { console.log('test: 12sad31'); } );
testing.cb.remove(testid);
testing.cb.add('doSay', function () { console.log('test: asdascccc'); } );
testing.cb.add('doSay', function () { console.log('test: qweqwe'); } );
testing.cb.add('doSay', function () { console.log('test: d121d21'); } );
testing.cb.add('doSay', function () { console.log('test: wwww'); } );
testing.say();
This always seemed the easiest for me to understand... Just create a new instance of the inherited class and then loop through its variables and methods and add them to the main one.
var myPerson = new Person()
var myPerson.firstName = 'john';
var myPerson.lastName = 'smith';
var myPerson.jobTitle = 'Programmer';
var Person = function(){
//Use this to inherit classes
this._extendedClass = new Person_Job();
for(var i in this._extendedClass){
this[i] = this._extendedClass[i];
}
delete this._extendedClass;
this.firstName = '';
this.lastName = '';
}
var Person_Job = function() {
this.jobTitle = '';
}
In the code below, I've got two objects declared, with one object inheriting the properties and functions of another.
I want to use the super variable to call the methods of the object I inherited from. When I trace out itemEditor, I can see the function and it's methods correctly. When I try to access the method of itemEditor, it returns undefined.
What am I doing wrong? Is there a better way to do this?
var myObject = {
itemEditor : function (vars) {
this.editItem = function () {
alert("Editing Item");
}
},
recurringItemEditor : function (vars) {
myObject .itemEditor.apply(this, [vars]);
this.prototype = myObject.itemEditor.prototype;
var super = myObject.itemEditor
this.editItem = function () {
console.log("fn.recurringItemEditor.editItem");
console.log(super);
console.log(super.editItem);
super.editItem.call(this);
}
}
Your code seems a little confused. On the one hand myObject.itemEditor is a constructor and therefore a function (myObject.itemEditor.apply(this, [vars])), and on the other you treat it like an object with a prototype (this.prototype = myObject.itemEditor.prototype;).
That's not even considering that super is a reserved keyword.
Your example may be simplifying something you are trying to do, but I don't see why you don't just use the usual prototype inheritance. That way you can still have a method in your local instance and call the prototype one within it if you want e.g.
recurringItemEditor : function (vars) {
this.prototype = new myObject.itemEditor(vars);
this.editItem = function () {
console.log("fn.recurringItemEditor.editItem");
console.log(this.prototype);
console.log(this.prototype.editItem);
this.prototype.editItem.call(this);
}
}
I used your advice and it works well now. In regards to treating it like a function and an object, myObject .itemEditor.apply(this, [vars]); was still required in order for the object to inherit the properties of itemEditor. I should have made that clear in the original code. If there's a better way to do this, let me know.
var myObject = {
itemEditor : function (vars) {
var myVars = vars + "foo";
this.editItem = function () {
alert(myVars);
}
},
recurringItemEditor : function (vars) {
myObject .itemEditor.apply(this, [vars]);
this.prototype = new myObject.itemEditor(vars);
this.editItem = function () {
console.log("fn.recurringItemEditor.editItem");
console.log(this.prototype);
console.log(this.prototype.editItem);
this.prototype.editItem.call(this);
}
}
}
I came up with a simple design pattern that was inspired by several other design patterns. Its main purpose is to have private methods (instead of all global), methods visually nested and grouped within an object, and having "self" as an available variable to access the scope, which is really useful when using calling functions with a callback parameter.
It seems to work fine, but is it safe (performance - and scope-wise) to do Obj.apply(Obj);?
The code:
function Obj() {
var self = this;
var privateFunc = function() {
console.log('private');
self.otherPublic();
};
self.publicFunc = function() {
console.log('pub1ic');
privateFunc();
};
self.otherPublic = function() {
console.log('pub2');
};
} Obj.apply(Obj);
I call it like this:
Obj.publicFunc();
Totally pointless brother. What you're doing by Obj.apply(Obj); is taking the function Obj, and adding to it those methods, in an unintuitive manner.
This:
var Obj = (function(){
var priv = function(){ console.log('2'); },
privVar = 6;
return {
pub1: function(){ console.log('1'); },
pub2: function(){ priv(); }
};
})();
Does the same thing, although better. I say better because (1) it's intuitive, and (2) Obj is now a simple javascript object (typeof Obj === 'object') whereas your Obj is a function with properties augmented (typeof Obj === 'function').
If you want a reference to self it's not hard (although it seems unnecessary), just create the object which will be returned at the top of the function, and augment the public methods, either at the end, or as you make them...
It's safe, but pointless.
Also, note that these methods won't scale well, because for each instance of Obj we create each function is recreated, which is memory-wise wasteful. This pattern above is fine because we created it with an anonymous function, so by definition there can only be one instance, although for types you need to instantiate multiple times the prototype should be used.
Don't be scared of it, it's there to be helpful.
UPDATE:
var Obj = (function(){
var priv = function(){ pub2(); },
privVar = 6,
pub1 = function(){ priv(); },
pub2 = function(){ console.log('1'); };
return {
pub1: pub1,
pub2: pub2
};
})();
Obj.pub1();
Notice that I call a public function, which calls a private function, which calls a public function - no special binding, no object reference.
UPDATE 2:
var Obj = (function(){
var public = {},
priv = function(){ public.pub2(); },
privVar = 6;
public.pub1 = function(){ priv(); },
public.pub2 = function(){ console.log('1'); };
return public;
})();
Obj.pub1();