Overiding a prototype method - javascript

I have a javascript base function like this;
roomBase = function () {
this.go = function(){
alert(1);
}
}
I have a room object like this;
myRoom = function(){
this.go = function(){
alert(456);
}
}
myRoom.prototype = new roomBase();
theRoom = new myRoom();
When I call theRoom.go() I am getting an alert from the prototype. What I want is the alert from the myRoom function instead.

It works fine for me. (it alerts 456)
Are you sure everything is running correctly?
Demo: http://jsfiddle.net/9hWAr/
Code for Demo:
var roomBase = function () {
this.go = function(){
alert(1);
}
}
var myRoom = function(){
this.go = function(){
alert(456);
}
}
myRoom.prototype = new roomBase();
var theRoom = new myRoom();
theRoom.go()

Related

Javascript method is not a constructor

at the company where Im at we use jquery and a lot of the code is very spaghetti haphazard code. So in an effort to organize it better im researching implementing the pub sub model described in this article
So I made a really basic version of it like so:
var topics = {};
jQuery.Topic = function( id ) {
var callbacks, method,
topic = id && topics[ id ];
if ( !topic ) {
callbacks = jQuery.Callbacks();
topic = {
publish: callbacks.fire,
subscribe: callbacks.add,
unsubscribe: callbacks.remove
};
if ( id ) {
topics[ id ] = topic;
}
}
return topic;
};
$(function() {
var testService = new TestService();
testService.subscribe();
var testView = new TestView(testService);
testView.initEvents();
});
/* ---------------------VIEW----------------- */
var TestView = function(testService) {
this.testService = testService;
};
TestView.prototype.initEvents = function () {
this.publishers();
};
TestView.prototype.publishers = function() {
$("#search").on("click", function () {
var isValid = this.testService.validateForm("#container");
if(isValid){
$.Topic( "search" ).publish();
}
})
};
/* ---------------------SERVICE----------------- */
var TestService = function() {
this.testIdea = [];
};
TestService.prototype.validateForm = function (section) {
var referralValid = true;
$(section).find('input,select').filter('[required]:visible').each(function (i, requiredField) {
if(requiredField.value === '') {
//'breaks' the loop out
referralValid = false;
return referralValid;
}
});
return referralValid;
};
TestService.prototype.search = function() {
};
TestService.prototype.subscribe = function() {
var self = this;
$.Topic("search").subscribe( function() {
self.search()
});
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div>
<div id="container">
<input type="text">
</div>
<button id="search">Search</button>
</div>
However when I put that in jsfiddle I get the error that Uncaught TypeError: TestService is not a constructor
in the stackoverflow snippet and on my local version I get a different error of Uncaught TypeError: Cannot read property 'validateForm' of undefined. I cant see what Im doing wrong. Any pointers?
You can declare constructor functions in the way you are doing it (assigning constructor to variable):
var TestView = function(testService) {
this.testService = testService;
};
Like in this simple example:
var myClass = function(name) {
this.name = name;
}
myClass.prototype = {
hello: function() {
console.log('Hello ' + this.name);
}
}
var me = new myClass('Andrew');
me.hello();
But you must remember to declare them before they are used. If you use function statement(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function) as suggested by Chad Watkins it helps only because of hoisting(http://adripofjavascript.com/blog/drips/variable-and-function-hoisting.html) not because of function statement being mandatory for constructors.
The error in your code is in line:
$("#search").on("click", function () {
var isValid = this.testService.validateForm("#container");
you are referencing jQuery object inside a callback not TestView instance, you probably wanted something like this(pun not intended):
...
var self = this;
$("#search").on("click", function () {
var isValid = self.testService.validateForm("#container");
...

OOJS call other method

var Lines = function(startXCon, endXCon,startYCon, endYCon)
{
this.drawCurve = function()
{
}
this.changeCurve = function(e)
{
//how can I call drawCurve from this method
}
}
The comment in my code explains the problem. Is this possible or are all methods private?
Like this:
var Lines = function(startXCon, endXCon,startYCon, endYCon){
var self = this; // store this as a variable to use in nested function
this.drawCurve = function(){}
this.changeCurve = function(e){
self.drawCurve(); //now call this.drawCurve()
}
}

javascript const in javascript library

I am trying to write a small javascript library as shown below. What I really want is when I call
console.log(tnd().pv);
it should output same number and not generate new number everytime. I know the issue is it calls Math.random everytime I console log. But how can I do so that it outputs same number?
(function () {
var tnd = function() {
return new tnlib();
};
var tnlib = function() {
this.version = function(){
console.log('1.0');
};
this.pv = Math.random()*10000000000000000;
};
if(!window.tnd) {
window.tnd = tnd;
}
})();
Don't execute Math.random() on each invocation of tnlib, but as a static variable:
(function () {
function tnd() {
return new tnlib();
}
function tnlib() {
}
tnlib.prototype.version = function(){
console.log('1.0');
};
tnlib.prototype.pv = Math.random()*10000000000000000;
if (!window.tnd) {
window.tnd = tnd;
}
}());
(or, if you really need to make pv an instance property):
var staticPv = Math.random()*10000000000000000;
function tnlib() {
this.pv = staticPv;
…
}

QUnit mocking out Autocomplete

In my QUnit test I want to mock out autocomplete method (jQuery UI), but every time I'm runing test like:
test("Create_PassedContainer_RunsAutocompleteOnMatchingElement",function(){
var $matchingInput = $('<input data-autocomplete-url="some"/>');
var $dom = $('<div><input/></div>');
$dom.append($matchingInput);
var autocompleteWasCalled = false;
$matchingInput.autocomplete = function(){ autocompleteWasCalled = true; };
new Autocomplete($dom);
ok(autocompleteWasCalled,"Should call autocomplete.");
});
I'm getting result:
TypeError: Object [object Object] has no method 'autocomplete'.
Code under test:
function Autocomplete($container) {
var $self = this;
this.Initialize = function($container) {
$self.$container = $container;
$self.$text = $('*[data-autocomplete-url]', $container);
$self.$value = $('input[type="hidden"]', $container);
$self.$text.autocomplete();
};
$self.Initialize($container);
};
Anything would be helpful.
Autocomplete is a plugin, try this:
var oldAutocomplete = $.fn.extend(true, {}, $.autocomplete);
$.autocomplete = function(){
autocompleteWasCalled = true;
}
/// Other code...
$.fn.autocomplete = oldAutocomplete;

JavaScript refer to a method inside a method?

Ok, just solved one problem where this refered to the wrong scope. Now I have another problem.
So I want to call a method that is inside a method. But I do not know how, check this source:
function someObj() {
var self = this;
this.someMethod1 = function() {
var elementBtn = document.getElementById('myBtn');
elementBtn.onclick = function() {
self.someMethod2.methodMethod();
//I want this.someMethod2.methodMethod() to be called
//...but I get an big error instead. Is it even possible?
//this.someMethod2() works fine.
};
};
this.someMethod2 = function() {
this.methodMethod = function() {
alert('THIS IS THE ONE I WANTED!');
};
alert('NO, NOT THIS!');
};
}
Error msg:
Uncaught TypeError: Object function () { ...
With your code, someMethod2 would need to execute first for the function expression to be assigned. Even then, it would be assigned to the parent instance.
Bearing in mind that all functions are objects in JavaScript, this is what you want instead:
this.someMethod2 = function() {
alert('NO, NOT THIS!');
};
this.someMethod2.methodMethod = function() {
alert('THIS IS THE ONE I WANTED!');
};
You are trying to use an object accessor on a function. If you want it to work in this way, you need to return an object literal from your call to the "outer" function.
this.someMethod2 = function() {
return {
methodMethod: function() {
alert('THIS IS THE ONE I WANTED!');
}
}
};
You can then chain the call. self.someMethod2().methodMethod();
While this is not directly possible, you can pass a "command" to the outer function to tell it to execute the inner function. But, are you sure this is what you really need? Perhaps you should use objects instead of functions here. But here's the "command" way:
this.someMethod2 = function(cmd) {
var methodMethod = function() {
alert('THIS IS THE ONE I WANTED!');
};
if (cmd === "methodMethod") {
methodMethod();
return;
}
alert('NO, NOT THIS!');
};
function someObj() {
var self = this;
this.someMethod1 = function () {
var elementBtn = document.getElementById('myBtn');
elementBtn.onclick = function () {
self.someMethod2().methodMethod();
};
};
this.someMethod2 = function () {
this.methodMethod = function () {
alert('THIS IS THE ONE I WANTED!');
};
//return this for chain method.
return this;
};
}
trying
function someObj() {
var self = this;
this.someMethod1 = function() {
var elementBtn = document.getElementById('myBtn');
elementBtn.onclick = function() {
self.someMethod2().methodMethod();
};
this.someMethod2 = function() {
this.methodMethod = function() {
alert('THIS IS THE ONE I WANTED!');
};
alert('NO, NOT THIS!');
return this;
};
}
Also if you use prototype then
function someObj() {
var self = this;
this.someMethod1 = function() {
var elementBtn = document.getElementById('myBtn');
elementBtn.onclick = function() {
self.someMethod2.methodMethod();//['methodMethod']();
};
};
this.someMethod2 = function() {
};
this.someMethod2.methodMethod = function() {
alert('THIS IS THE ONE I WANTED!');
};
};
But the method methodMethod is static

Categories