Calling function of instances in Javascript - javascript

I am trying create a hashmap in View function having instances of subviews , which I do in init method of View. But it is giving an error that init() of view doesnt exist. Am I doing anything wrong here? Thanks in advance.
http://jsfiddle.net/3fR4R/1/
view = function() {
var subview;
init = function() {
subview['search'] = new searchSubView();
}
}
check = function() {
console.log("clicked");
var view1= new view();
view1.init();
}
searchSubView = function() {
}

You've created a function and assigned it to an implicit global, which has nothing to do with the view function or instances created by it.
You can assign the function either by assigning to this.init within the constructor, or by putting it on view.prototype.
So either:
view = function() {
var subview;
// Note: You need code here to initialize `subview`
this.init = function() {
subview['search'] = new searchSubView();
};
};
or (note that I've made subview a property):
view = function() {
this.subview = /* ...initialize subview... */;
};
view.prototype.init = function() {
this.subview['search'] = new searchSubView();
};
Side notes:
You're falling prey to The Horror of Implicit Globals a lot in that code. You need to declare variables.
The overwhelming convention in JavaScript code is to use initial capitals for constructor functions, e.g., View rather than view.
You're also relying on automatic semicolon insertion, which I wouldn't recommend. Learn the rules and apply them, not least so you can minify/compress/compact your code safely.

Related

Overwriting Javascript method outside class, with default behavior

I'm trying to understand Javascript OOP. I'm trying to overwrite a method inside a class. The class has a default functionality when a 'click' in made. I want to override that function, so something new happens when a click is made.
I have a Javascript class that looks like this:
AlertModal = function(){
var x = *this is my close object;
x.onclick = destoryAlert;
function destroyAlert(){
console.log('destroy');
}
}
My HTML file shows:
<script type="text/javascript">
window.alert = function (message) {
var newAlert = new AlertModal();
newAlert.destroyAlert = function(){
console.log('new alert destroy');
};
newAlert.destroyAlert();
};
I get 'new alert destroy' which is great. But when I click the 'x', it says destroy as well. So it is overwritten, but not?! It's like it creates a new 'destroyAlert' function, when it's called, but leaves the default.
Can anyone please show me how I would do this, to create a class, with default functionality, but how to overwrite it if needed?
I'm use to programming in Java and Actionscript, extending classes and overwritting public/protected methods, but doing it Javascript seems so much different and I can't understand the logic to do so.
Thanks,
You can override methods on instance level:
AlertModal = function() {
this.init();
};
AlertModal.prototype.init = function() {
var modal = this;
var x = ...;
x.onclick = function() {
// Note that I'm not using `this` here, because it would
// reference `x` instead of the modal. But we can pass the modal
// from the outer scope. This is called a lexical closure.
modal.destroy();
};
};
AlertModal.prototype.destroy = function() {
console.log('destroy');
};
var myalert = new AlertModal();
myalert.destroy = function() {
console.log('new destroy');
};
myalert.destroy();
But if you want to do the same override in multiple places, it would probably be better to create a specialized OtherAlertModal by inheriting from AlertModal class. Here's a good approach to inheritance in JavaScript: http://ejohn.org/blog/simple-javascript-inheritance/
x.onclick = destroyAlertl
sets x's onclick handler to a reference local function
whereas
newAlert.destroyAlert = ...
sets this object's destroyAlert property set to a different function. It does not change the reference stored in x.onclick.
You need to put the "default" function on the prototype of AlertModal:
AlertModal.prototype.destroyAlert = function() {
...
}
and register the handler differently:
var self = this;
x.onclick = function() {
self.destroyAlert();
}
If you subsequently overwrite the destroyAlert property of such an object then the new function will be called instead.

Can an instance of a class replace itself in JavaScript?

I have a variable in a global scope which is assigned an instance of a class like this:
window.someInstance = new MyClass();
At some point later, I need to replace that variable with a new instance, but is it possible/acceptable to do that from within a method of the class itself? For example:
function MyClass () {
this.myClassMethod = function () {
window.someInstance = new MyClass();
};
}
window.someInstance = new MyClass();
window.someInstance.myClassMethod.call();
An odd scenario I know but it works cleanly, I'm just not sure if this creates any memory or referencing issues?
Only if everyone always accessess the instance indirectly via window.somereference. As soon as anyone does var x = window.someinstance then you lose the indirection and your trick would stop working.
You might acheieve a more robust implementation by placing the indirection in a variable of the instance itself instead of in a global variable
function Instance(){
this.impl = ...;
}
Instance.prototype = {
changeImpl: function(){ this.impl = new Impl(); },
//delegate all other methods
f1: function(){ return this.impl.f1(); }
}

How to create a javascript class or module, I need 2 instances on a page

I am wrapping common javascript functions that will work on elements on a page.
My page has 2 of these elements (textareas), so I will need to create 2 instances and then I want to do this:
var textArea1 = new SomeClass();
var textArea2 = new SomeClass();
textArea1.init("ta1");
textArea2.init("ta2");
I tried doing this the module pattern way, but I'm confused how I can create 2 seperate instances of it?
var MYMODULE = function() {
var _init = function(ta) {
// ..
}
return {
init: function(ta) {
_init(ta);
}
};
}();
Use a constructor function:
function SomeClass(id) {
this.id = id;
// ...
}
Usage:
var textArea1 = new SomeClass("ta1");
var textArea2 = new SomeClass("ta2");
You can put methods for the class in the prototype for the function. Example:
SomeClass.prototype = {
getValue: function() { return document.getElementById(this.id).value; }
};
Usage:
var text = testArea1.getValue();
Using your specific example, you could just MYModule twice, but it's a weird pattern that doesn't seem to do a whole lot.
Simple example how instantiation works:
function SomeClass() {
// constructor
}
SomeClass.prototype.init = function(ta) {
// ..
}
var textArea1 = new SomeClass();
var textArea2 = new SomeClass();
textArea1.init('ta1');
textArea2.init('ta2');
But regardless, you may like Backbone.js
Your MYMODULE idea will work fine. As above and then
MYMODULE.init("ta1");
MYMODULE.init("ta2");
This line here will not care it is called with two different parameters
var _init = function(ta) {
// ..
}
It is just a place to hold a function. The real question is what is inside that function.
For example if it works with ta in some standard way (attaches event handlers, does some styling.. ) then it will not be a problem. The issue will be if you use MYMODULE local variables and expect to have more than one of them. You only have one MYMODULE so local variables will be shared with this design. This might be what you want. I'm not sure.
This pattern can work fine for a control passed in having special data all itself. The best way to do this -- since you are using jQuery is with the data function... thus the code could look like:
var _init = function(ta) {
jQuery.data(ta,"foo", 10);
// etc
}

How to isolate my javascript code to prevent collisions?

I have been writing a lot of javascript functions and event listeners and I want to move them into their own namespaced, isolated place that doesn't conflict when I concatenate and minify it with my other javascript files.
I am still new to javascript, so there may be simple solution to this answer. I started by creating a javascript object:
var MySpecialStuff = {
init: function(){
//do everything here
}
};
Then in my html, on the page I want to use it on I can initialize this code:
<script>
MySpecialStuff.init();
</script>
But then the init method started growing and I need to start breaking that code into smaller chunks, but I am stuck on the syntax and how to set private methods/variables and call them from within the init method and other private methods. How can I do this?
Am I headed in the right direction? What other ways can I / should I go about doing this sort of thing?
You are headed in the right direction. You can use the module pattern to create an object with private members and methods like this:
var foo = function(){
var bar = ""; //private
function funk(){
//private function
return "stuff";
}
return{
getBar: function(){
return bar;
},
init: function(){
alert(funk());
},
randomMember: 0 //public member
}
}();
Only what's in the return block is public, but you can call any private methods/access any private methods from within the return block.
Thanks to Joseph for linking to another SO question which explained this approach:
Another way to do it, which I consider to be a little bit less restrictive than the object literal form:
var MySpecialStuff = new function() {
var privateFunction = function() {
};
this.init = function() {
};
};
I like to further segment my code into a more modular approach. So, let's say we have a page that has a list of blog posts, a page menu, and a sidebar. I'd end up with this:
var blog_controller = {
init: function(){
document.getElementById('some_element').addEvent('click', this.handleSomeClick);
this.applySomePlugin();
},
applySomePlugin: function () {
/* do whatever needs to happen */
},
handleSomeClick: function () {
// scope will be element
this.style.color = 'red';
}
};
var page_menu_controller = {
init: function(){
document.getElementById('some_other_element').addEvent('click', this.handleSomeClick);
},
handleSomeClick: function () {
// scope will be element
this.style.color = 'blue';
}
};
... and so on. This keeps code organized by purpose, helps keep scope clear, and allows you to reuse elements of code that might occur frequently (for instance, if you AJAX'd in a new blog post, you could call this.applySomePlugin again).
This of course is a quick-and-dirty example, but I hope you get the idea
Divide responsibility of code you have put inside the init function into subobjects of the main object.
MySpecialStuff = {
// Variables/constants and everything else that needs to be accessed inside the whole MySpecialStuff object
init: function(){
//Do only whats required to be globally initiated.
this.MainMenu.init(); // Main menu stuff usually is.
}
};
MySpecialStuff.MainMenu = {
// Variables / constants that are only important to the MainMenu subobject.
init: function(){
//Just the initiation stuff thats related to the MainMenu subobject.
}
};
MySpecialStuff.SlideShow = {
// Variables / constants that are only important to the SlideShow subobject.
init: function(){
// Same as for the MainMenu with the difference that nonessential objects can be "fired" when required
}
};

JavaScript: Public methods and prototypes

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.

Categories