I'm having a little trouble working out how my JavaScript should be structured, etc..
My OOP skills in languages such as PHP, ActionScript 3 and so on are what I'm assuming to be on-par, but JS is lacking this which has thrown me off quite a bit in my learning.
I have a vague understanding of the prototype feature which I used a little in AS2 - I believe this is the closest I'll be able to get. At the moment, I'm laying out my code similar to this:
var slideshow =
{
property: value,
/**
* This is a method
*/
myMethod: function()
{
// do method things
}
};
// ------
slideshow.property ++;
slideshow.myMethod();
This all works okay, but it's void my ability to do something like:
var myslideshow1 = new Slideshow();
var myslideshow2 = new Slideshow();
myslideshow1.property = 10;
myslideshow2.property = 16;
I'm not sure on how to go about creating two different instances of one "object" I've created (in this case, slideshow).
I can't find any resources that explain the prototype feature in a way that makes sense.
Any pointers would be supoib.
Any javascript function can act as a constructor for a class, so try this:
function SlideShow(params) {
return {
property: value,
myMethod: function() {
//do method things
};
};
};
var slideshow1 = new SlideShow(params);
slideshow1.property = 10;
//etc.
I would frown apon using prototype to add methods to a class as there could be performance issues
Here is a sample class structure you could use. JavaScript classes are not much different the functions.
function MyItem(){
this.d = '';
this.clear = function( ) {
this.d = '';
}
}
var myItem = new MyItem( )
myItem.d = "test";
alert(myItem.d);
myItem.clear();
alert(myItem.d)
Some good reading here
You should avoid using the new operator, everything is public. A better way to do what you want to do, and have private variables and functions is to do the following:
var slideshow = function () {
var self = {};
var private_param = "hello";
var private_func = function(say) {
alert(say);
};
var method = function() {
private_func(private_param);
};
var param = 500;
self.method = method;
self.param = param;
return self;
// return object, with the method func and param param publicly accessible
// private_param and private_func are not accessible to the outside
};
var presentation = slideshow(); // new slideshow, you could edit to pass in init params
presentation.method(); // hello
Related
Considering object creation patterns with private properties, one way to do is :
function MyStack (){
var list = [],
index = 0;
this.push = function(val){
return list[index++] = val;
};
this.pop = function(){// ...}
}
var stack1 = new MyStack(); stack1.push(5);
var stack2 = new MyStack(); stack2.push(11);
Problem with this: Every instance of Stack has it's own copy of methods 'push' and 'pop'.
Another way for implementing constructor method is:
function MyStack(){
this.list = [];
this.index = 0;
}
MyStack.prototype = {
insert: function(val){
return this.list[this.index++] = val;
},
pop:function(){//...}
}
Problem here: We lose the privacy of list and index.
Is there a way, such that we can have both methods reuse among instances and privacy of properties ?
I understand that we can have this for methods that don't operate on any state of the object, but I am talking more about those methods that do operate on the state.
Yes. I've edited this code so it's actually fully functional as you had intended it to work. It seems a bit redundant to me, but, it does provide you the ability to provide a public interface, but to keep your variables private and control the way the user interacts with them.
function MyStack(){
var list = [];
var index = 0;
this.getIndex = function(){
return index;
}
this.setIndex = function(val){
index = val;
}
this.list = function(val){
if(val){
// setter if a value was provided. Illustrating how you can control
// index, which I assume is the point of having these things private
// to begin with
return list[this.setIndex(this.getIndex() + 1)] = val;
}
// always return list - acts like a getter
return list;
}
}
MyStack.prototype = {
insert: function(val){
return this.list(val);
},
pop:function(){}
}
var stack1 = new MyStack();
stack1.insert(5);
var stack2 = new MyStack();
stack2.insert(11);
You should check out John Resig's Simple Javascript Inheritance. It is a great read, and it has been extended to provide support for privates, aptly called Privates.js;
A constructor function may return any object (not necesserily this). One could create a constructor function, that returns a proxy object, that contains proxy methods to the "real" methods of the "real" instance object. This may sound complicated, but it is not; here is a code snippet:
var MyClass = function() {
var instanceObj = this;
var proxyObj = {
myPublicMethod: function() {
return instanceObj.myPublicMethod.apply(instanceObj, arguments);
}
}
return proxyObj;
};
MyClass.prototype = {
_myPrivateMethod: function() {
...
},
myPublicMethod: function() {
...
}
};
The nice thing is that the proxy creation can be automated, if we define a convention for naming the protected methods. I created a little library that does exactly this: http://idya.github.com/oolib/
I think in both approaches you mentioned, When ever object is created using constructor pattern the properties will get copied to its objects. This you mentioned for the 1st approach as the concern. I feel the same will be applied for the second approach also along with your concern in this approach.
We generally go to the second approach you mentioned when ever we want to extend the properties of "MyStack" to some other class.
Lets say i want to extend your class MyStack to MyTest like below
var dummy = function();
dummy.prototype = MyStack.prototype;
var MyTest = function(){
};
MyTest.prototype = new dummy(); // Assigning MyStack properties to MyTest
var obj = new MyTest();
How can I add data/functions to all instances of a javascript object created by a constructor so that all instances have the same reference and not a copy of it?
Basically implementing the equivalent of a static method in C#.
For example, given the following code which creates a Widget class.
(function() {
var Widget = function() {
};
Widget.prototype.init = function(data) {
this.data = data;
};
this.Widget = Widget;
}).call(this);
var instance1 = new Widget();
instance1.init('inst1');
var instance2 = new Widget();
instance2.init('inst2');
alert(instance1.data); // inst1
alert(instance2.data); // inst2
In the above case each instance has it's own copy of the data property. However I want to add a function that sets data for all current and future instances.
My current solution is to add a function to the constructor function object, not to it's prototype. See below for example. Is there any pitfalls to this and is there a better way?
(function() {
var Widget = function() {
};
Widget.prototype.init = function(data) {
this.data = data;
};
Widget.addStaticData = function(data) {
this.staticData = data;
};
Widget.prototype.getStaticData = function() {
return Widget.staticData;
};
this.Widget = Widget;
}).call(this);
var instance1 = new Widget();
instance1.init('inst1');
Widget.addStaticData('static');
var instance2 = new Widget();
instance2.init('inst2');
alert(instance1.data); // inst1
alert(instance2.data); // inst2
alert(instance1.getStaticData()); // static
alert(instance2.getStaticData()); // static
Three pitfalls that I can think of:
methodological: the prototype is the place for shared, reused, inherited functionality/properties - utilise it as such
performance: it is quicker to inherit than to set each time on an instance. John Resig (jQuery creator) did some benchmarking on this in a blog post that I appear unable to find at present.
losing the split between inherited and own properties. If you apply everything to an instance via the constructor, everything is an instance property.
Everything via constructor:
function Dog() { this.legs = 4; }
var fido = new Dog();
fido.name = 'Fido';
for (var i in fido) if (fido.hasOwnProperty(i)) alert(i+' = '+fido[i]);
...alerts both properties as they are deemed the instance's own.
Via prototype and constructor
function Dog2() { }
Dog2.prototype.legs = 4;
var fido = new Dog2();
fido.name = 'Fido';
for (var i in fido) if (fido.hasOwnProperty(i)) alert(i+' = '+fido[i]);
...alerts just name because that is the only instance property. (Nonetheless, fido.legs is retrievable - but it comes from the prototype).
[EDIT - in response to the OP's commet below]
If you want a static method, then that should be added to the function after its declaration.
function Dog() {}
Dog.static = function() {}
Consider a local variable staticData instead of the Widget.staticData property. That way, an external command won't be able to write the data directly, so the only way to write it will be through the addStaticData function:
(function () {
var Widget = function () {};
var staticData;
Widget.addStaticData = function ( obj ) {
staticData = obj.data;
};
Widget.prototype.init = function () {
var data = staticData;
// use data
// or just use the staticData variable directly
};
this.Widget = Widget;
}).call( this );
With your code, one could just execute this:
Widget.staticData = { data: 'COMPROMISED!' };
to change the static data. Since you have a dedicated function for setting the static data, you probably don't want it to be possible to change the static data in other ways.
With my code, the above statement has no effect, and the static data can only be changed via the addStaticData function.
function Foo() {
this.SayFoo = function() {
console.log('Foo');
};
}
function Bar() {
this.SayBar = function() {
console.log('Bar');
};
}
Foo.prototype = new Bar();
var fooBar = new Foo();
fooBar.SayBar();
This obviously works, but is it the correct way to do it?
Is there any way to make use of jQuery's $.extend or something similar in order to achieve the same inheritance results?
Including other frameworks besides jQuery is not an option in this case.
There are actually multiple ways to do inheritance in JavaScript: neoclassical, prototypal, and functional. Douglas Crockford has nothing but bad things to say about neoclassical inheritance—the method you have above, and the method most Java/C# developers think will be the most natural. The reason revolves around all the awkward things you have to do to get it right—setting the prototype, setting the constructor, etc. Also, setting the prototype to a new instance of the parent class, like you have above, is usually frowned upon strongly, I believe because it complicates handling parameters with the base ctor.
If you're really sold on the neoclassical method, here's a great link that really goes over it.
The key part I reproduce for you here:
function Inherit(sub,super){
var thinF = function(){};
thinF.prototype = super.prototype;
sub.prototype = new thinF();
sub.prototype.constructor = sub;
sub.super = super.prototype;
if( super.prototype.constructor == Object.prototype.constructor ){
super.prototype.constructor = super;
}
}
FWIW Here's an example of functional inheritance that also highlights something you don't get with the neoclassical method: encapsulation/information hiding.
function eventRaiser(protectedStuff) {
protectedStuff = protectedStuff || {};
var that = {};
var events = {}; //private
protectedStuff.raise = function(key) {
if (!events[key]) return;
for (var i = 0; i < events[key].funcs.length; i++)
events[key].funcs[i].apply(null, Array.prototype.slice.call(arguments, 1));
};
that.subscribe = function(key, func) {
if (!events[key])
events[key] = { name: key, funcs: [] };
events[key].funcs.push(func);
};
return that;
}
function widget() {
var protectedStuff = {};
var that = eventRaiser(protectedStuff);
that.doSomething = function() {
alert("doing something");
protectedStuff.raise("doStuffEvent");
};
return that;
}
$(function() {
var w = widget();
w.subscribe("doStuffEvent", function(){ alert("I've been raised"); });
w.doSomething();
w.protectedStuff.raise("doStuffEvent"); //error!!!!! raise is protected
w.raise("doStuffEvent"); //and this obviously won't work
});
Yes, setting prototype to an instance is the correct way to do it.
I am involved in a web application project at the moment and we are not going to be using a framework.
I am looking for the 'best' javascript inheritance implementation. I have worked with prototypal style classes as follows:
function animal(options) {
self = this;
//properties
this.name = options.name;
//events
this.onXYZ = options.onXYZ;
//event handlers
this.handlerOfEvent = function() {
//do something using 'self' as the 'this' variable
}
}
animal.prototype.aFunction = function()
{
//do something
}
etc.
I have not used inheritance without a framework (usually use Mootools) but I do understand to a point how it works in Javascript and have seen a fair few implementations.
I wanted to get some feedback on where I could find the best implementation, one that doesn't fiddle with any native types and allows me full access to the ascendant classes' properties and functions.
Any pointers would be greatly appreciated.
Thanks very much for your time.
There's a method described by (who else) Douglas Crockford that I've been partial to as of late:
var rectangle = function(width, height)
{
var h = height, w = width;
var scale = function(s)
{
h = h * s;
w = w * s;
}
return { scale: scale };
}
var square = function(width)
{
var o = rectangle(width, width)
// Add things to o, if needed
return o;
}
Not a terribly good example, as nothing is really being extended, but it should get the idea across. In order to instantiate these objects, simply use this:
var newRectangle = rectangle(3, 4); // 3 by 4 rectangle
var newSquare = square(6); // 6 by 6 square
I tried many approaches in the past. I like John Resig way of implementation the most. It's very simple. You can see full example and javascript file (only around 25 lines of code) from http://ejohn.org/blog/simple-javascript-inheritance/
Just to complete the answer, you can implement a class like this after include his code..
var Person = Class.extend({
name : '',
init : function (name) {
this.name = name;
},
say : function () {
alert("I'm " + this.name);
}
});
var mick = new Person("Mick");
mick.say();
Take a look at Simple Javascript Class Project (constant, property, protected, static, utils, and more), Simple JavaScript Inheritance and Inheritance Patterns in JavaScript.
Simple Javascript Class (sjsClass) Example
Class.extend('Foo', {
__protected : {
privV : 123,
privF : function () {
return this.privV + this.priv3;
}
},
'protected priv3' : 'Protected Value',
setX : function (x) {
this.privV = x;
},
test : function () { return this.privF(); }
});
var f = new Foo;
f.setX(456);
f.test(); // -> 'Protected Value456'
f.privF(); // -> Error
f.privV; // -> undefined
f.priv3; // -> undefined
You should check the videos from Douglas Crockford about "parasatic inheritance".
Here's a basic example
var pkg={};//simulating a package
pkg.ObjA=function (){
var privateField;//every inner function will have a closure to this field, this is the way to simulate private fields
var privatefunc=function(){
//same for private functions
};
//use object augmentation to add different fields to the "that" reference
that.publicMethod=function(){
//do something
};
return that;
}
//create two different instance of the object A
var instance1=pkg.ObjA();
var instance2=pkg.ObjA();
pkg.ObjB=function(){
//the that of this object is based on the ObjA
var that=pkg.ObjA();
//specialize the that to simulate inheritance
that.newMethod=function(){
}
return that;
}
var child=pkg.ObjB();
I'm not entirely sure how to implement OOP concepts in JS.
I have a class which is entirely declared in its constructor:
function AjaxList(settings)
{
// all these vars are of dubious necessity... could probably just use `settings` directly
var _jq_choice_selector = settings['choice_selector'];
var _jq_chosen_list = settings['chosen_list'];
var _cb_onRefresh = settings['on_refresh'];
var _url_all_choices = settings['url_choices'];
var _url_chosen = settings['url_chosen'];
var _url_delete_format = settings['url_delete_format'];
var jq_choice_selector_form = _jq_choice_selector.closest("form");
if (DEBUG && jq_choice_selector_form.length != 1)
{
throw("There was an error selecting the form for the choice selector.");
}
function refresh()
{
_updateChoicesSelector();
_updateChosenList();
_cb_onRefresh();
};
AjaxList.prototype.refresh = refresh; // will this be called on all AjaxLists, or just the instance used to call it?
// AjaxList.refresh = refresh; // will this be called on all AjaxLists, or just the instance used to call it?
// ...
}
There are multiple instances of AjaxList. When I call refresh() on one of them, I want only that one list to refresh itself. In the following instance:
term_list = AjaxList(settings);
term_list.refresh();
The refresh() call seems to make all the AjaxLists refresh themselves. What is the correct way to do this?
I'm using jQuery, if it makes any difference.
You should not redefine the prototype function in the constructor.
If you want to create a privileged function use this.methodname = ... from the constructor.
function AjaxList() {
var privateVar = 0;
function privateFunction() {
//...
}
//create a refresh function just for this instance of the AjaxList
this.refresh = function() {
//privileged function, it can access the 'privateVar & privateFunction'
privateVar++;
}
}
//public functions that don't need access to the private variables/functions
AjaxList.prototype.publicFunction=function() {
};
Also if you want to create a proper object, you need to change
term_list = AjaxList(settings);
to
term_list = new AjaxList(settings);
AjaxList = function(settings) {
this._jq_choice_selector = settings["choice_selector"];
this._jq_chosen_list = settings["chosen_list"];
this._cb_onRefresh = settings["on_refresh"];
this._url_all_choices = settings["url_choices"];
this._url_chosen = settings["url_chosen"];
this._url_delete_format = settings["url_delete_format"];
this.jq_choice_selector_form = _jq_choice_selector.closest("form");
if (DEBUG && jq_choice_selector_form.length != 1) {
throw "There was an error selecting the form for the choice selector.";
}
};
AjaxList.prototype = {
_updateChoicesSelector: function() { },
_updateChosenList: function() { },
_cb_onRefresh: function() { },
refresh: function() {
this._updateChoicesSelector();
this._updateChosenList();
this._cb_onRefresh();
}
};
Given that structure, you should be able to call:
var ajaxList = new AjaxList(settings);
ajaxList.refresh(); // etc.
I'm using jQuery, if it makes any
difference.
No it doesn't. See my answer here: What's the difference between Javascript, Jquery and Ajax?
I have a class which is entirely
declared in its constructor
There are no classes in Javascript. Forget them. You really need to learn some of the basics of this language in order to use them. It's not Java, even though it looks similar.
If you have a Constructor Function it will create an instance. The shared methods will be in the prototype chain, and only instance specific data goes right into the function with the this keyword.
So the basic concept of an object would look like this:
// constructor of an instance
function MyObject( param1, param2 ) {
this.param1 = param1;
this.param2 = param2;
this.param3 = 32;
return this; // [optional]
}
// Public methods can be called by any instance.
// Instances share their prototype object.
// The this keyword always points to the current
// instance that calls the method.
MyObject.prototype.sum = function() {
return this.param1 + this.param2 + this.param3;
}
// refresh should be a shared method, since it
// does the same thing on every instance
MyObject.prototype.refresh = function() {
// do the refresh
// ...
}
The power of this concept is that there is only one refresh function in memory. And it can deal with any instance. In addition, if another object inherits from MyObject the refresh function will be inherited. But in the memory there will be still one shared refresh function. And it can deal with any of the parent or child instances.