Extend prototype with another prototype - javascript

How can I extend prototype A with prototype B, so whenever I call prototype A, both will be executed?
var Helper = function() {
}
Helper.prototype.resizer = function() {
$('body').append(' Window resized ');
}
var Something = function() {
// Extend Helper.resizer with Something.anything
// extend(Helper.resizer, this.anything);
}
Something.prototype.anything = function() {
$('body').append(' Run this on resize to ');
}
var help = new Helper();
var some = new Something();
$(window).on("resize", function(){
help.resizer();
});
Made an example at codepen:
http://codepen.io/robbue/pen/892c8f61e1b5a970d6f694a59db401a6
jQuery allowed, or just vanilla.

I don't really understand your question because prototypes are not executed, but I think you want something like this:
var Helper = function() {}
Helper.prototype.resizer = function() {
$('body').append(' Window resized ');
}
var Something = function(h) {
var oldresizer = h.resizer,
that = this;
h.resizer = function() {
var res = oldresizer.apply(this, arguments);
that.anything();
return res;
};
}
Something.prototype.anything = function() {
$('body').append(' Run this on resize to ');
}
var help = new Helper();
new Something(help);
$(window).on("resize", function(){
help.resizer();
});
or that:
function Helper() {}
Helper.prototype.resizer = function() {
$('body').append(' Window resized ');
}
function Something() { // inherits Helper
Helper.apply(this, arguments);
}
Something.prototype = Object.create(Helper.prototype);
Something.prototype.anything = function() {
$('body').append(' Run this on resize to ');
};
Something.prototype.resizer = function() {
Helper.prototype.resizer.call(this);
this.anything();
};
var help = new Something(help);
$(window).on("resize", function(){
help.resizer();
});

Related

Is it possible to unit-test this javascript structure?

Given the following JavaScript structure:
addClickEvent: function() {
element.addEventListener('click', function() {
self.a();
self.b();
});
},
Is it possible to assert that a() and b() have been called without refactoring out the anonymous function or editing it's contents?
Assuming the self in your code is the window.self property.
You could do something like this:
function element_onclick_callsAandB() {
// Arrange
var aCalled = false;
var bCalled = false;
var element = ...;
var origA = self.a;
var origB = self.b;
self.a = function() {
aCalled = true;
origA();
};
self.b = function() {
bCalled = true;
origB();
};
try {
// Act
element.click();
// Assert
assertTrue(aCalled);
assertTrue(bCalled);
}
finally {
self.a = origA;
self.b = origB;
}
}

jquery object - function undefined error

In the following function, my objects inside floatShareBar function is undefined. Do I have to init or define a var before the functions? it throws me js error : .float - function undefined.
(function($) {
.
.
.
$("body").on("ab.snap", function(event) {
if (event.snapPoint >= 768) {
floatShareBar.float()
} else {
floatShareBar.unfloat();
}
});
var floatShareBar = function() {
var fShareBar = $('#article-share');
this.float = function() {
console.log(
};
this.unfloat = function() {
console.log("unfloat");
};
};
.
.
.
})(jQuery);
You need to get an instance of that function with a self instantiating call:
var floatShareBar = (function() {
var fShareBar = $('#article-share');
this.float = function() {
console.log('float');
};
this.unfloat = function() {
console.log("unfloat");
};
return this;
})();
UPDATE 1: I modified it to create an object within the function to attach those functions to, since in the previous example this refers to the window object
var floatShareBar = (function() {
var fShareBar = $('#article-share');
var instance = {};
instance.float = function() {
console.log('float');
};
instance.unfloat = function() {
console.log("unfloat");
};
return instance;
})();
UPDATE 2: You can actually just use the new keyword as well, look here for more info
var floatShareBar = new (function() {
var fShareBar = $('#article-share');
this.float = function() {
console.log('float');
};
this.unfloat = function() {
console.log("unfloat");
};
})();
Change you function to this:
$("body").on("ab.snap", function(event) {
if (event.snapPoint >= 768) {
(new floatShareBar()).float()
} else {
(new floatShareBar()).unfloat();
}
});
function floatShareBar () {
var fShareBar = $('#article-share');
this.float = function() {
console.log(
};
this.unfloat = function() {
console.log("unfloat");
};
};
you should declare functions when using var before you call them.

How can I add OOP to these JS functions?

I know this may seem like a repeated question, but I am currently stuck as to the best way to approach this, limited mostly by my lack of knowledge. Thus I am here to learn.
I am trying to do some simple OOP with JavaScript but coming from C# I am having a few issues with how to best solve this problem. Below I have four "Classes"; DisplayEngine, DisplayElement, Box, and Grid.
I would like Box and Grid to inherit DisplayElement, and be able to call the base functions in each of their respective functions. Almost like super.call() or something.
How would you best approach this?
var DisplayEngine = function() {
this.elements = [];
this.add = function(element) {
this.elements.push(element);
};
this.update = function() {
this.elements.forEach(function(element) {
element.update();
})
};
this.draw = function() {
this.elements.forEach(function(element) {
element.draw();
})
};
};
var DisplayElement = function() {
this.update = function() {
console.log('DisplayElement update');
};
this.draw = function() {
console.log('DisplayElement draw');
};
};
var Box = function() {
this.update = function() {
console.log('Box update');
// call DisplayElement.update()
};
this.draw = function() {
console.log('Box draw');
// call DisplayElement.draw()
};
};
var Grid = function() {
this.update = function() {
console.log('Grid update');
// call DisplayElement.update()
};
this.draw = function() {
console.log('Grid draw');
// call DisplayElement.draw()
};
};
$(function() {
var displayEngine = new DisplayEngine();
var box = new Box();
var grid = new Grid();
displayEngine.add(box);
displayEngine.add(grid);
displayEngine.update();
displayEngine.draw();
});
Here is a way to do it with prototype, each "class" need to be in his own file, the important part is Grid.prototype = new DisplayElement(); This allow you to call function from the DisplayElement in Grid:
DisplayEngine.js
function DisplayEngine() {
this.elements = [];
}
DisplayEngine.prototype.add = function(element) {
this.elements.push(element);
}
DisplayEngine.prototype.update = function() {
this.elements.forEach(function(element) {
element.update();
})
}
DisplayEngine.prototype.draw = function() {
this.elements.forEach(function(element) {
element.draw();
})
}
DisplayElement.js
function DisplayElement() {
}
DisplayElement.prototype.updateElement = function() {
console.log('DisplayElement update');
}
DisplayElement.prototype.drawElement = function() {
console.log('DisplayElement draw');
}
Box.js
function Box() {
}
Box.prototype = new DisplayElement();
Box.prototype.update = function() {
console.log('Box update');
this.updateElement();
}
Box.prototype.draw = function() {
console.log('Box draw');
this.drawElement();
}
Grid.js
function Grid() {
}
Grid.prototype = new DisplayElement();
Box.prototype.update = function() {
console.log('Grid update');
this.updateElement();
}
Box.prototype.draw = function() {
console.log('Grid draw');
this.drawElement();
}
Main.js
$(function() {
var displayEngine = new DisplayEngine();
var box = new Box();
var grid = new Grid();
displayEngine.add(box);
displayEngine.add(grid);
displayEngine.update();
displayEngine.draw();
});
To just answer to your question, declare your objects such as :
function DisplayElement() {};
DisplayElement.prototype.update = function() {
console.log('DisplayElement update');
};
DisplayElement.prototype.draw = function() {
console.log('DisplayElement draw');
};
// ...
// Now, instanciation :
var myElement = new DisplayElement();
Then, for inheritance :
function Box() {
DisplayEngine.call(this, arguments); // Call the super constructor
}
Box.prototype = Object.create(DisplayEngine.prototype); // "Apply" the inheritance
Box.prototype.constructor = Box; // Redefine the constructor to Box because it was overriden by the previous line
I disagree about those saying that you doesn't need "classes" in Javascript. In implementations such as Node.js which will handle datas must have, in my opinion, classes. It's easier (always in my opinion) to read, maintain, and use.
You can use the prototypal style like what Shryme explained, or you can use a library that mimcs the classical oop style in javascript, check Classing{js} : http://www.classingjs.co.nf/

"This" not refering to current object

I am kind of new to OOP in JS. I would like to know why when creating sub-objects, this stops referring to the main object AFTER the second level of subobjects.
function Clase()
{
this.__construct = function()
{
this.paginator();
alert('__construct finished');
};
this.paginator = function()
{
this.paginator.title = function()
{
this.paginator.title.set_offsets = function()
{
alert('paginator.title.set_offsets executed!');
};
};
this.paginator.title(); //instantiating
alert('subobject paginator created');
};
this.__construct();
}
var instancia = new Clase();
instancia.paginator.title.set_offsets();
http://jsfiddle.net/WYWwE/
The error is: this.paginator is undefined.
And now, if I use closures, it works perfectly:
function Clase()
{
self = this;
this.__construct = function()
{
this.paginator();
alert('__construct finished');
};
this.paginator = function()
{
self.paginator.title = function()
{
self.paginator.title.set_offsets = function()
{
alert('instancia.paginator.title.set_offsets() executed');
};
};
self.paginator.title();
alert('this.paginator created');
};
this.__construct();
}
var instancia = new Clase();
instancia.paginator.title.set_offsets();
http://jsfiddle.net/esjHu/
So, AFAIK after some point, "this" stops refering to the class "Clase" and refers to something else. If so, is it a good practice to use closures this way?
Is it also correct to start the class with self = this; and from then on use ONLY "self"? for instance: http://jsfiddle.net/byGRX/
You lose the reference to the "original" this when you nest functions. To remedy do the following:
function Clase() {
var that = this;
this.paginator = {
title: {
set_offsets: function() {
alert('paginator.title.set_offsets executed!');
}
}
};
};
var foo = new Clase();
foo.paginator.title.set_offsets();​
http://jsfiddle.net/vd5YK/
You don't lose reference to the this object, here's what happens:
For example:
function Class() {
this.func1 = function () {
this.func1.func2 = function () {
alert('Works!');
};
};
this.func1.func2();
}
x = new Class();
Now, the reason you get an error saying that func2 doesn't exist is because the function object for func2 isn't constructed until you call func1:
function Class() {
this.func1 = function () {
this.func1.func2 = function () {
alert('Works!');
};
};
this.func1();
this.func1.func2();
}
x = new Class();
And now it works.
EDIT:
So, why doesn't this work:
function Class() {
this.func1 = function() {
this.func1.func2 = function() {
this.func1.func2.func3 = function() {
alert('works!');
};
this.func1.func2.property = 5;
};
};
this.func1();
this.func1.func2();
}
x = new Class();
x.func1.func2.func3();
Basically, what your trying to do is add a property named property and a method named func3 to the function object of func2, but the problem is that func2 isn't constructed before calling func1. It's the same as doing:
function Class() {
this.func1 = function() {
this.func1.func2 = function() {};
};
this.func1.func2.func3 = function() {
alert('works!');
};
this.func1.func2.property = 5;
this.func1();
this.func1.func2();
}
x = new Class();
x.func1.func2.func3();
If you want it to work you need first construct the function object for func2 by calling func1:
function Class() {
this.func1 = function() {
this.func1.func2 = function() {};
};
this.func1();
this.func1.func2.func3 = function() {
alert('works!');
};
this.func1.func2.property = 5;
// this.func1.func2();
}
x = new Class();
x.func1.func2.func3();
alert(x.func1.func2.property);

Can't get two functions to initialize each other

function funcA() {
var fB;
function init() {
fB = new funcB(false); //error here
}
init();
}
function funcB(usefuncA) {
var fA;
function init() {
if (usefuncA) fA = new funcA();
}
init();
}
$(function() {
var test = new funcB(true);
});
I know how to get around this problem in C++, but no idea what tricks there are to fix it in javascript. There is a way, though, right? I absolutely must have each function in the other, and the only other alternative I can think of is putting the contents of funcB in its own .js file then using PHP to create two versions of funcB, one for funcA to use and one in current place of funcB. But that's ridiculous...
This code (your original code, minus the unneeded call to jquery) works fine for me. There's no error.
You can run it here (take a look at the console).
function funcA() {
var fB;
function init() {
fB = new funcB(false); //error here
}
init();
}
function funcB(usefuncA) {
var fA;
function init() {
if (usefuncA) fA = new funcA();
}
init();
}
var test;
test = new funcA();
console.log(test);
test = new funcB();
console.log(test);
test = new funcB(true);
console.log(test);
​
You need to avoid the infinite loop.
function funcA(B) {
var fB;
var that = this;
function init() {
fB = B || new funcB(that);
}
init();
}
function funcB(A) {
var fA;
var that = this;
function init() {
fA = A || new funcA(that);
}
init();
}
$(function() {
var test = new funcB();
});​
(function (testFuncA, $, undefined) {
testFuncA.init = function(caller) { // do stuff },
} (window.testFuncA= window.testFuncA|| {}, jQuery));
(function (testFuncB, $, undefined) {
testFuncB.init = function() { testFuncA.init(this); },
} (window.testFuncB= window.testFuncB|| {}, jQuery));
Do you mean something like this?
function funcA() {
var fB;
this.init = function() {
fB = new funcB(false); //error here
}
}
function funcB(usefuncA) {
var fA;
this.init = function init(usefuncA) {
if (usefuncA) fA = new funcA();
}
}
$(function() {
var test = new funcB();
test.init(true);
});
Is it maybe this what you are looking for?
FuncA = function () {
var fB; this.init(); };
FuncA.prototype.init = function () {
this.fB = new FuncB(false); };
FuncB = function (usefuncA) {
var fA; this.init(usefuncA); };
FuncB.prototype.init = function (usefuncA) {
var fA; if (usefuncA) { this.fA = new FuncA(); } };
var test = new FuncB(true);

Categories

Resources