Prototype method not being called - javascript

I'm creating a custom object on click and then trying to access it's prototype's methods.
$(function(){
$('.addtask').on("click", function(){
var new_task = new Task();
$('.deletetask').on("click", function(){
new_task.deleteTask();
});
function Task(){
this.html="<li>Add Description<span class='deletetask'></span></li>";
}
Task.prototype = {
constructor: Task,
deleteTask: function(){
this.remove()
},
}
});
});
Now when i click on class deleteTask it says:
TypeError: new_task.deleteTask is not a function
new_task.deleteTask();
How can I access the prototype method deleteTask() ??

You're setting the prototype of Task after you've created your new Task. You're not changing the prototype of your already created instances by doing so, as the prototype is referenced at the instance creation.
Move the Task.prototype = { assignation before the creation of your new Task.
If you really want to add a function to all instances after they're created, change the prototype of the constructor instead of replacing it :
Task.prototype.deleteTask = function(){...

You should move the definition of Task and its prototype methods before the initial .on call. This will incidentally fix the problem identified by #dystroy whereby you're trying to set the prototype of Task after creating an instance of it.
As written the Task function is recreated every time the click handler is invoked, and therefore the Task objects created on each click will be instances of different classes, which makes using the prototype moot. Prototype methods are an effective way of sharing methods amongst multiple instances, and achieving inheritance, but you're using neither.
Alternatively, leave the Task function where it is but abandon using prototype methods, e.g.:
function Task() {
this.html = "<li>Add Description<span class='deletetask'></span></li>";
this.removeTask = function() {
this.remove();
}
}
(NB: this.remove is also undefined at this point?)

Related

Function prototypes

I have a function called Observable. As per all functions, I can call certain methods on the function, that even though they do not exist directly on the function, JS moves 'down the prototypical chain' and gets the method on the function. Example of such methods is 'toString()'
function Observable(forEachy) {
this._forEachy = forEachy;
}
console.log(Observable.toString()) // "function Observable(forEach) {this._forEach = forEach;}"
Now, when I set Observable.prototype to a new object and define some methods in that object, and call those methods on Observable, it throws an error.
Observable.prototype = {
forEachy: function (onNext) {
return onNext();
}
}
console.log(Observable.forEachy(()=>"Hi, John")) // error: Observable.forEachy is not a function
But I can call those methods on the prototype and it works just fine.
console.log(Observable.prototype.forEachy(()=>"Hi, John")); // "Hi, John"
Setting a new instance to Observable just works fine.
const abc = new Observable("HI");
console.log(abc.forEachy(()=>"Hello world")); // "Hello world"
Please, why is that?
Also, apart from passing in the argument received in the constructor to the newly created object, what else does the statement this._forEachy = forEachy do?
const abc = new Observable("HI");
console.log(abc._forEachy) // "HI"
Your example works as expected. You should consider getting more information about Prototypes in JavaScript.
When you declare something as Function.prototype = function(){}, it works similar to methods in OOP programming. In oop you can't call Class.method(), can you? You have to first create an instance to call this method. However, keep in mind that there is a lot of differences between OOP and prototype inheritance. In reality, your "prototype" is not the abstraction. It's the existing object :)
Though, if you want to follow this way, you can create class and define static method:
class Observable {
static forEachy(){
// your code here
}
}
and then:
Observable.forEachy()

Javascript Prototype What is Correct?

Hey guys i have a question regarding prototype in javascript.
Which of the following is the correct and best way to use prototype and why?
var myClass = function(){
this.anotherFunction();
}
myClass.prototype.anotherFunction = function(){
console.log('my prototype function');
}
var foo = new myClass(); // which automaticaly performs the function
OR
var myClass = function(){
}
myClass.prototype.anotherFunction = function(){
console.log('my prototype function');
}
var foo = new myClass();
foo.anotherFunction(); // performs the function only when called
Thanks!
The first implementation calls a method directly from the constructor. These methods are quite often some kind of initialization methods that build the needed inner state of the this context. In non JavaScript appropriate OOP speak this would mean that a method is called directly from your class constructor that builds up some initial state.
The second implementation exposes the prototype function anotherFunction as part of the public interface.
In short: Both variants are correct but implement different concepts

How do you override bindings up a JS constructor chain?

I'm trying to define a base class in JavaScript that performs a lot of common functionality upon creation. Part of that functionality is to create a component and register callback handlers to that component.
The problem I'm having is how to override the function that's being used for that callback handler in child classes that extend my base class.
In concrete terms I have a BasicPage component that creates a Table component. The BasicPage also defines a default onRowClick function that gets registered with the newly created Table.
Now I want to create a PageWithSections component that extends BasicPage (via a call(..) statement) and overrides onRowClick. The problem is the registration of the click handler with the table happens within the constructor of the base class. At the time of that registration, onRowClick hasn't been overridden yet, so the reference is to the base classes version of onRowClick.
I've made a jsBin that illustrates the problem.
http://jsbin.com/uDEjuzeQ/9/edit
If you click on each box once, in order, I want the message box display to be:
No messages yet;
row clicked;
row clicked; BasicPage onRowClicked;
row clicked; PageWithSections onRowClicked
What is the proper way to override a function up the constructor chain and bind the overridden function to something during construction of a base object?
UPDATE
This question original referenced a prototype chain, but in truth the prototypes are not actually being used in this example.
The question was updated to reflect that. This ends up being more of a question about late binding.
The biggest issue I see is that your _onRowClicked (the callback you pass into the Table) is not actually defined in a prototype anywhere.
You are not actually using prototypical inheritance - you are defining the methods inside the constructor, and calling one constructor from another.
Try refactoring your code such that some of the default behaviour for BasicPage is defined in BasicPage.prototype (which is currently not referenced/altered at all). At that point, a solution that uses prototypical inheritance might suddenly become obvious. :)
Here is some code that should work:
var BasicPage = function(){
this.name="BasicPage";
document.body.onclick=this._getClick(this);
};
BasicPage.prototype._getClick=function(me){
return function(e){
console.log("target is:,",e.target);
console.log("this is:",me.name);
}
};
var PageWithSections = function(){
//initialise parent and it's instance members
BasicPage.call(this);
//override name
this.name="PageWithSections";
};
PageWithSections.prototype=Object.create(BasicPage.prototype);
PageWithSections.prototype.constructor=PageWithSections;
var sect = new PageWithSections();
document.body.click();
The following code demonstrates how you could extend the onclick handler without copy and pasting the BasicPage code you already have:
var BasicPage = function(){
this.name="BasicPage";
document.body.onclick=this._getClick(this);
};
BasicPage.prototype._getClick=function(me){
return function(e){
console.log("re used code from BasicPage");
console.log("target is:,",e.target);
console.log("this is:",me.name);
}
};
var PageWithSections = function(){
//initialise parent and it's instance members
BasicPage.call(this);
//override name
this.name="PageWithSections";
};
//set prototype chain
PageWithSections.prototype=Object.create(BasicPage.prototype);
PageWithSections.prototype.constructor=PageWithSections;
//extend _getClick
PageWithSections.prototype._getClick=function(me){
var fn=BasicPage.prototype._getClick.call(me,me);
return function(e){
//do BasicPage click code
fn(e);
//extended code
console.log("with a little extra from PageWithSections");
};
};
var sect = new PageWithSections();
document.body.click();
More info on prototype and constructor functions here. The introduction should be very helpful and if you have time I would suggest reading all to get a good understanding of JS prototype.
My co-worker came up with one possible solution. As #cloudfeet said, it's not prototypal, but it works.
Basically he set the binding to a different instance function that in turn, called the _onRowClick function which at the time of execution would have been overridden.
http://jsbin.com/uDEjuzeQ/16/edit

Javascript object properties access functions in parent constructor?

So I'm using this pretty standard jquery plugin pattern whereby you can grab an api after applying the jquery function to a specific instance.
This API is essentially a javascript object with a bunch of methods and data.
So I wanted to essentially create some private internal methods for the object only to manipulate data etc, which just doesn't need to be available as part of the API.
So I tried this:
// API returned with new $.TranslationUI(options, container)
$.TranslationUI = function (options, container) {
// private function?
function monkey(){
console.log("blah blah blah");
}
// extend the default settings with the options object passed
this.settings = $.extend({},$.TranslationUI.defaultSettings,options);
// set a reference for the container dom element
this.container = container;
// call the init function
this.init();
};
The problem I'm running into is that init can't call that function "monkey". I'm not understanding the explanation behind why it can't. Is it because init is a prototype method?($.TranslationUI's prototype is extended with a bunch of methods including init elsewhere in the code)
$.extend($.TranslationUI, {
prototype: {
init : function(){
// doesn't work
monkey();
// editing flag
this.editing = false;
// init event delegates here for
// languagepicker
$(this.settings.languageSelector, this.container).bind("click", {self: this}, this.selectLanguage);
}
}
});
Any explanations would be helpful. Would love other thoughts on creating private methods with this model too.
These particular functions don't HAVE to be in prototype, and I don't NEED private methods protected from being used externally, but I want to know how should I have that requirement in the future.
// Edited based on Matthew's comment
So I tried moving the prototype definition based on Matthew's comment. This seems to work now, but still not sure if this is the correct way to be doing this. Thoughts? Obviously it would be cleaner if I move the prototype object into a separate area
$.TranslationUI = function (options, container) {
function monkey(){
console.log("blah blah blah");
}
// extend the default settings with the options object passed
this.settings = $.extend({},$.TranslationUI.defaultSettings,options);
// set a reference for the container dom element
this.container = container;
$.extend($.TranslationUI.prototype,
{
init : function(){
monkey();
// editing flag
this.editing = false;
// init event delegates here for
// languagepicker
$(this.settings.languageSelector, this.container).bind("click", {self: this}, this.selectLanguage);
}
}
);
// call the init function
this.init();
};
So while this works, the crappy part is that I'm re-initing prototype every time that constructor runs. I'm sure that's not efficient. But not sure how else to have the prototype methods have access to private functions/variables of a certain instance.
The error is because monkey is not defined in the scope you're calling $.extend from.
Alright. So found an answer on stackoverflow, confirmed by Crockford's site.
javascript - accessing private member variables from prototype-defined functions
Essentially, you can't really get access to private functions from the prototype methods. You can via 'privileged' functions, which in turn call private variables and functions, but then you are basically creating a crapload of getters and setters, which might just be doubled in your prototype "public" methods.
So its kind of a lot of work, especially if your stuff doesn't TRULY need to be private.
Have a look at my answer and some of the others here:
call function inside a nested jquery plugin

Javascript Object Inheritence

I'm creating a control for Google maps v2. While creating my control I've found a design challenge and want to find an appropriate solution. Here's the goods.
A custom Google control inherits from GControl;
myControl.prototype = new GControl();
Next I need to overload the initializer so here it is.
myControl.prototype.initilize = function (map) {
//do some work and return stuff
};
Now within my custom controls initlize function I create a couple elements which, using the GEvent class, I subscribe to various events. To make my callback functions managable, I included them into the controls prototype.
myControl.prototype.onEvent = function(e){
//do some work;
//modify the members of the current myControl instance
};
Within my callback function "onEvent" I want to modify members within my control. What is the best way to access my control from the function? The keyword "this" cannot be used because that is a reference to the element that was clicked, in my case a div. And I can't access the members through the prototype because I need a specific instance of the object. The only viable solution I've considered is to create my control globally in one of my scripts. Is this the best method?
The easiest thing that I can think, it to define your onEvent method within your constructor, there you will have quick access to the current object instance, and you will not have to modify your public API:
function MyControl () {
var instance = this; // store a reference to 'this'
this.onEvent = function (e) {
// use the instance variable
instance.otherMethod();
};
}
Note that in this approach, the onEvent property will exist physically in your object instances (obj.hasOwnProperty('onEvent') = true).
Edit: You can simply use the GEvent.bind function:
GEvent.bind(map, "click", myObj, myObj.onEvent);
The above bind method will enforce the context, so the this keyword inside myObj.onEvent will point to the myObj object instance when the event is triggered, it will work with your code without problems.
I'm not familiar with how you subscribe to events using GEvent, so I'll make that part up. Do this:
myControl.prototype.onEvent = function(e, instance) {
// do some work
// modify members of 'instance'
};
function wrap(handler, instance) {
return function(e) {
handler(e, instance);
}
}
GEvent.Register('Event', wrap(instance.onEvent, instance));

Categories

Resources