How to invoke javascript OOPS based class in another javascript - javascript

I have a javascript class called "LayoutProcessor".js ,defined as follow:
define('layoutProcessor', ['jquery'], function($) {
"use strict";
function LayoutProcessor() {
return (this);
}
LayoutProcessor.prototype.process = function() {
console.log('inside process');
};
LayoutProcessor.prototype.responseHandler = function() {
console.log('inside responseHandler');
};
return new LayoutProcessor();
});
I am trying to access the method "process" in another javascript class called "test.js", which is defined as follow:
test.js
require(['LayoutProcessor.js','jquery'], function(layoutProcessor,$) {
$(document).ready(function(){
var response = new LayoutProcessor().process();
});
})
But I am getting a type error:
new LayoutProcessor() is not a constructor.

As per the implementation by OP, it should be
var response = layoutProcessor.process();
not
var response = new LayoutProcessor().process();
Please refer the fiddle
The error message is appropriate, as its not a constructor but an object.
new LayoutProcessor() is not a constructor.
LayoutProcessor.js returns an Object.
return new LayoutProcessor();

There are few things going on with those code.
The way it is current written, LayoutProcessor module returns a constructed object, not a constructor to call.
To call it you would use:
var response = layoutProcessor.process();
However, this makes a singleton, which I doubt is what you mean.
In a singleton, there will only be one instance if layoutProcessor, since that instance is created by the LayoutProcessor module.
I believe the code that you mean would be more like this, where you create a new instance of the object for everyone that needs it:
layoutProcessor
define('layoutProcessor', ['jquery'],
function($) {
"use strict";
//----------------------------------------
/**
* constructor
*/
function LayoutProcessor() {
return (this);
}
LayoutProcessor.prototype.process = function() {
console.log('inside process');
};
LayoutProcessor.prototype.responseHandler = function() {
console.log('inside responseHandler');
};
// Note: Return a FUNCTION reference to be called later.
return LayoutProcessor;
}
);
test.js
require(['LayoutProcessor.js', 'jquery'],
function(LocalLayoutProcessor, $) {
$(document).ready(function() {
var response = new LocalLayoutProcessor().process();
});
}
)

Only issue is return statement. it should be
return LayoutProcessor;

Related

JS closure to return object instance as interface

I have the following code.
function Test() {
this.funct_1 = function() {
alert('funct_1');
}
this.funct_2 = function() {
alert('funct_2');
}
return this;}
function getTestObj() {
var testObj;
if (!testObj) {
testObj = new Test();
}
return function() {
return testObj;
}}
What I'm trying to accomplish is the following. I want to have a class Test which is not singleton. Then in some other places in my application I need to have a function which could return the same instance per script execution. I figured that I could use closure for that getTestObj.
However, when I try to use it
getTestObj().funct_1();
I'm getting the following error, saying the funct_1() is not found.
Cannot find function funct_1 in object function () {...}.
Clearly, I'm making some kind of mistake here, but I'm not able to find any solution over the net which could help me. Would appreciate any comments.
NOTE: I'm forced to use ECMA5
testObj is wrapped inside a function
So, either call it
getTestObj()().funct_1(); //notice two ()()
Save the value of getTestObj() in a variable
var singleTon = getTestObj();
var testObj = singleTon();
testObj.funct_1();
Or, simply return testObj (in case singleTon isn't required)
function getTestObj()
{
var testObj;
if (!testObj) {
testObj = new Test();
}
return testObj;
}
And invoke it as
getTestObj().funct_1(); //notice single ()
getTestObj() is returning a function i.e. :
function() {
return testObj;
}
So you have to call it again getTestObj()(), this will return the Test's object and now you can access it's properties.
getTestObj()().funct_1();
OR
You can change your getTestObj function as :
function getTestObj() {
var testObj;
if (!testObj) {
testObj = new Test();
}
return (function() {
return testObj;
}());
}

Mocking/spying on a constructor "x.Thing()"

Assuming x is an external library and Thing is an object that can be constructed from x. This is all wrapped in an Angular service, like so:
app.service('thingService', function() {
var thing;
this.createThing = function(thingParam){
thing = new x.Thing(thingParam);
}
});
My initial attempt included this:
xSpy = jasmine.createSpyObj('x', ['Thing']);
spyOn(window, 'x').andReturn('xSpy');
But it still complains that x() method does not exist on that line that Thing should be constructed
Your attempt
xSpy = jasmine.createSpyObj('x', ['Thing']);
spyOn(window, 'x').andReturn('xSpy');
is wrong:
spyOn() replaces methods with spies, since x is an object this won't work. This is why you get the exception x() method does not exist.
Assuming your example you can just replace the attribute:
describe("Test", function() {
var origThing;
beforeEach(function() {
// create spy object for Thing that provides its methods
var mockedThingInterface = jasmine.createSpyObj('Thing', ['methodA', 'methodB']);
mockedThingInterface.methodA.and.returnValue(1);
mockedThingInterface.methodB.and.returnValue(2);
// remember original constructor
origThing = x.Thing;
// replace the constructor
x.Thing = function() {
return mockedThingInterface;
}
});
afterEach(function() {
// restore when finished
x.Thing = origThing;
});
it("should ...", function() {
// ...
});
});

Getting "Undefined is not a function" error when using the Revealing Prototype Pattern

I'm trying to employ the Revealing Prototype Pattern in a JavaScript file to encapsulate two collections of related functions. But when the page loads, it returns the following error at the call to the .init function:
"Uncaught TypeError: Undefined is not a function."
Here is the pattern for my markup.
<script>
$(function () {
testProto1.init();
testProto2.init();
});
</script>
And here is the pattern in my JavaScript file.
var testProto1 = function () {
};
testProto1.prototype = function () {
var init = function () {
alert("init 1");
};
return {
init: init
}
}();
var testProto2 = function () {
};
testProto2.prototype = function () {
var init = function () {
alert("init 2");
};
return {
init: init
}
}();
This is probably some basic syntax error on my part, and I do apologize if it's a duplicate. Why am I seeing this error and how do I fix it? Thanks.
It looks like you're using the concepts of prototypes & function instances incorrectly in a lot of ways.
You need to instantiate a function with the new operator if you want to be able to access prototypes.
From what it looks like you're trying to achieve this:
var testProto1 = function () { };
// Create your methods in object notation within your prototype
testProto1.prototype.init = function () {
alert('init called');
};
Now if you want to call this, you have to instantiate it!
var proto1 = new testProto1();
// NOW you can call .init! Because the prototype was actually created
proto1.init(); // alerts 'init called!'
you can access prototype's properties from instances of this Object, so this will work:
var a=new testProto1();
a.init();
if you want to acces init function from testProto1 you must write:
testProto1.prototype.init();
so your code will look like:
$(function () {
testProto1.prototype.init();
testProto2.prototype.init();
});

JS turning a function into an object without using "return" in the function expression

i have seen in a framework (came across it once, and never again) where the developer defines a module like this:
core.module.define('module_name',function(){
//module tasks up here
this.init = function(){
//stuff done when module is initialized
}
});
since i never saw the framework again, i tried to build my own version of it and copying most of it's aspects - especially how the code looked like. i tried to do it, but i can't seem to call the module's init() because the callback is still a function and not an object. that's why i added return this
//my version
mycore.module.define('module_name',function(){
//module tasks up here
this.init = function(){
//stuff done when module is initialized
}
//i don't remember seeing this:
return this;
});
in mycore, i call the module this way (with the return this in the module definition):
var moduleDefinition = modules[moduleName].definition; //the callback
var module = moduleDefinition();
module.init();
how do i turn the callback function into an object but preserve the way it is defined (without the return this in the definition of the callback)?
you have to use:
var module = new moduleDefinition();
and then you're going to get an object.
Oh, and maybe you want to declare init as this:
this.init = function() {
Cheers.
How about something like this (I can only assume what mycore looks like):
mycore = {
module: {
definitions: {},
define: function(name, Module) {
this.definitions[name] = new Module();
this.definitions[name].init();
}
}
};
mycore.module.define('module_name', function () {
// module tasks up here
this.init = function () {
// init tasks here
console.log('init has been called');
};
});
I don't know what framework you're using or what requirements it places on you, but Javascript alone doesn't require a function to return anything, even a function that defines an object. For example:
function car(color) {
this.myColor = color;
this.getColor = function() {
return this.myColor;
}
//note: no return from this function
}
var redCar = new car('red');
var blueCar = new car('blue');
alert(redCar.getColor()); //alerts "red"
alert(blueCar.getColor()); //alerts "blue"
One more alternative http://jsfiddle.net/pWryb/
function module(core){this.core = core;}
function Core(){
this.module = new module(this);
}
Core.prototype.modules = {};
module.prototype.define = function(name, func){
this.core.modules[name] = new func();
this.core.modules[name].name = name;
this.core.modules[name].init();
// or
return this.core.modules[name];
}
var myCore = new Core();
var myModule = myCore.module.define('messageMaker', function(){
this.init = function(){
console.log("initializing " + this.name);
}
})
myModule.init();

Javascript inheritance and method overriding

Assume I have a class like this:
function Widget() {
this.id = new Date().getTime();
// other fields
}
Widget.prototype = {
load: function(args) {
// do something
}
}
From this class I created some other classes which inherit the same prototype but have some added methods. What I want to do is being able to define a load() method in the sub-classes which first calls the parent method and then execute some code. Something like:
SpecialWidget.prototype = {
load: function(args) {
super.load(args);
// specific code here
}
}
I know there's no super keyword in Javascript but there must be a way to do this.
You can simulate it like this:
SpecialWidget.prototype = {
load: function(args) {
Widget.prototype.load.call(this, args);
// specific code here
}
}
Or you can create your own super property like this:
SpecialWidget.prototype.parent = Widget.prototype;
SpecialWidget.prototype = {
load: function(args) {
this.parent.load.call(this,args);
// specific code here
}
}
so first, you set up your 'subclass' like so
function SubClass(name) {
Super.call(this);
// stuff here
}
SubClass.prototype = new SuperClass(null);
SubClass.prototype.constructor = SubClass;
and then you can do
SuperClass.prototype.theMethod.apply(this);
from within a subclass implementation to specifically invoke the super's implementation.
I don't know if this is the best solution, but you could do something like this:
function Widget() {
this.id = new Date().getTime();
}
Widget.prototype.load = function(args) {
alert( 'parent load' );
};
SpecialWidget = function(){};
// Make the prototype of SpecialWidget an instance of Widget
var proto = SpecialWidget.prototype = new Widget;
// Give the prototype a function that references the "load" from Widget
proto.parent_load = proto.load;
// Give SpecialWidget its own "load" that first calls the parent_load
proto.load = function( args ) {
this.parent_load( args );
alert( 'special load' );
};
var inst = new SpecialWidget;
inst.load();
This makes the prototype of SpecialWidget an instance of Widget so that it inherits all that Widget has.
Then it makes a reference to the load() of Widget called parent_load(), and creates its own load() that calls the parent_load() when invoked.
Since mid-2015 (ECMAScript 2015), javascript has Classes and super
Here's the link: https://262.ecma-international.org/6.0/, see section 12.3.5 (super) and 14.5 (Class definitions).
How your code would look with those changes:
class Widget() {
constructor() {
this.id = new Date().getTime();
// other fields
}
load(args) {
// do something
}
}
class SpecialWidget extends Widget {
load(args) {
super.load(args);
// specific code here
}
}
The closest I got to the previous syntax (without using class but using super) was using Object.setPrototypeOf:
// UNCHANGED
function Widget() {
this.id = new Date().getTime();
// other fields
}
Widget.prototype = {
load: function(args) {
// do something
}
}
// slightly changed to declare SpecialWidget
function SpecialWidget() {}
// changed to define load as an method, and not a property with function as value
SpecialWidget.prototype = {
load(args) {
super.load(args);
// specific code here
}
}
// here's the key
Object.setPrototypeOf(SpecialWidget.prototype, Widget.prototype);
The declaration of load was changed because super can be used inside methods, but not functions. So, instead of load: function(args) { body }, it's simply load(args) { body }.
But, there's a caveat: with this solution, elements of SpecialWidget will not inherit the id defined as new Date().getTime(). I don't think there's a workahound (without using classes or duplicating code declaring this.id inside SpecialWidget).
It would be possible to store the old value of the load method in a closure, if you did your overriding like this:
function Widget() {
this.id = new Date().getTime();
// other fields
}
Widget.prototype = {
load: function(args) {
// do something
alert("Widget Prototype Load");
}
};
function SpecialWidget(){
};
SpecialWidget.prototype = new Widget();
(function(){
var oldLoad = SpecialWidget.prototype.load;
SpecialWidget.prototype.load = function(){
oldLoad();
alert("new Load");
};
}());
var x = new SpecialWidget();
x.load();
It works, but I'm not sure if it's the best method.
Using Simple Javascript Class:
Class.extend('Widget', {
load: function () {
alert('foo');
}
});
Widget.extend('SpecialWidget', {
load: function () {
this.super();
alert('bar');
}
});
new Widget().load(); // Alert: 'foo'
new SpecialWidget().load(); // Alert: 'foo' and 'bar'
Take a look at Simple Javascript Class Project, Simple JavaScript Inheritance and Inheritance Patterns in JavaScript.

Categories

Resources