--
Hello SO, Today i come before you with a humble question, As I'm obviously missing something fairly basic.
I'm trying, And I can't see why it shouldn't work, To "extend" a function.
To be specific, Consider the following code :
It appears that variables have gone missing from the console.log even though they're defined.
However this doesn't seem like the right way to implement what i'm trying to achieve.
The requirement : `Extending a function with variables and methods so that all new instances of that function will receive those variables. What you could consider 'class variables'.
Super = function (){}; //yes it's global.
Super.prototype.alert = function()
{
console.log('alert function');
}
ExtendSuper = function(arguments) //yes it's global
{
**EDIT , THIS IS THE ANSWER THANKS TO YURY**
return function () {
return new Super(arguments);
}
}
arguments = {} //some object with variables and functions
ExtendedFunction = ExtendSuper(arguments); //yes it's global
success = new ExtendedFunction();//yes, it's global
EDIT: OP has changed the question in a way making code example irrelevant. Good for him!
You have some weird ideas about inheritance actually. I do recommend you to rethink your application before its too late. :) You do need prototypes because they are essential part of javascript.
Anyway http://jsfiddle.net/uj4ag/
var DomDom = (function(){ //Do not need a function? Use IEFE
function View(bootstrap) //my "view" class
{ var view = this;
view.$elm = false; view.model = false;
view.render = function()
{
console.log('rendering something');
}
$.extend(view,bootstrap);
};
return {
View: View,
extend: {
View: function(params) {//Let's create a new function :)
return function() { //it is not an inheritance it is 'currying'
return new View(params);
}
}
}
}
}());
var SubClass = DomDom.extend.View({
foobar : true,
alert : function () { alert('hi')},
render : function() { console.log('rendering something else')},
});
var viewInst = new DomDom.View;
var subClassInst = new SubClass();
viewInst.render();
subClassInst.render();
Related
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;
}());
}
I have the following javascript class/instantiation/method call:
var myClass = function(a){
var myElement = a,
myMethod = function(){
alert(myElement.html());
}
return {
myMethod: myMethod
}
}
var myObj = new myClass($('#elementA'));
myObj.myMethod();
And my markup:
<div id="elementA">This is the text in elementA</div>
Here is the fiddle.
Is there a way to instantiate this class with dot syntax? Ideally, it would look like: myObj.myClass()? Identical to how jquery instantiates new widgets ($().tabs(); comes to mind). Would I need to restructure my object? If so, how?
If you can infer that I am misunderstanding how any part of this works, please feel free to correct me. Thanks for the help!
This is the way I would go about something like this:
var myObj = {
myMethod: function(elem) {
alert($(elem).html()); //do your alert
return this; //return the object for chanining
},
myOtherMethod: function() {
alert("This is something other method");
return this;
}
}
myObj.myMethod("#elementA").myOtherMethod();
Here's the fiddle: http://jsfiddle.net/LqvXg/
Just create a new object with the var name of whatever you want.
If you're going to use new, you should probably use it with a constructor. You could also use Object.create() and pass the prototype.
The only time I return an object with methods is when I am using closures and I have variables that need to change... A perfect example would be something like a timer.
New fiddle: http://jsfiddle.net/WybQb/2/
What is wrong with just chaining all of it? Though, if you intend on doing things like this... I'm going to get shot down for suggesting this, but this syntax might be awesome for you:
var myClass = function(a){
var myElement = a,
myMethod = function(){
alert(a.html());
}
return {
myMethod: function() { return new myMethod(); }
}
}
The only benefit of this is to avoid the new keyword.
i'm fighting around with oop in javascript for a few days now but i don't find a solution.
I've created 3 objects, a super class, a child class and an inheritance_manager which should do all the "prototype"-magic on my child classes.
The inheritance manager:
Inheritance_Manager = {};
Inheritance_Manager.extend = function(subClass, baseClass) {
function inheritance() {
}
inheritance.prototype = baseClass.prototype;
subClass.prototype = new inheritance();
subClass.prototype.constructor = subClass;
subClass.baseConstructor = baseClass;
subClass.superClass = baseClass.prototype;
};
The super (parent) class:
SDSection = function(sectionId, resourceId) {
this.self = this;
this.sectionId = sectionId;
this.resourceId = resourceId;
...
};
SDSection.prototype.doSetups = function() {
...
};
The child class:
TypedSectionHandler = function(sectionId, resourceId) {
SDSection.call(this, sectionId, resourceId);
...
};
Inheritance_Manager.extend(TypedSectionHandler, SDSection);
TypedSectionHandler.prototype.doSetups = function() {
...
SDSection.doSetups.call(this);
...
};
What i want to do is simple in other programming languages like php or java. I want to call the overwritten "doSetups"-method in the parent class "SDSection" from the method "doSetups" in child classes of type "TypedSectionHandler".
I'm struggling around with this problem for round about 1 week now and i tried different solutions, from basic to more complex, but nothing seems to work.
Everytime the script is executed for e.g. in chrome or firefox i will get the error "cannot call method call on undefined" or more simpler, "SDSection.doSetups" is not defined.
At least i picked up the above approach from here and adapted it to my needs but it does not work anyway and the browser are quitting with the same error. Slowly i'm getting seriously nuts. :)
Does somebody know what i'm doing wrong and how a working solution will look like?
Thanks
Udo
You need to call the doSetups function that is part of the parent class's prototype.
TypedSectionHandler.prototype.doSetups = function() {
...
SDSection.prototype.doSetups.call(this);
...
};
If you want to look at different techniques for inheritance (particularly, one which does not require the caller to know the parent type), you may want to check out CoffeeScript's __extends function, and how it performs inheritance.
Use voithos' solution if you are doing pure javascript. I like to use John Resig's simple inheritance snippet in my current projects. It's only 521 bytes after minification, with no dependencies, and in your case it would work like this:
SDSection = Class.extend({
init: function(sectionId, resourceId) {
this.sectionId = sectionId;
this.resourceId = resourceId;
...
},
doSetups: function(){
...
}
});
TypedSectionHandler = SDSection.extend({
doSetups: function(){
...
this._super();
...
}
});
If you want to do it by yourself, you can go the way like voithos said - writing it on your own helps you understand js OOP for sure.
If you want to have more comfort (= not having to use apply and call and - if you're developing in Visual Studio 2012 - base-methods/-constructor intellisense support) I would like you to check out a framework I wrote: jsframework
With it you can write your sample really easy:
SDSection = new Class(Object, function(base, baseConstructor)
{
// member fields for prototype
this.self = null;
this.sectionId = -1;
this.resourceId = -1;
// constructor
this.init = function(sectionId, resourceId)
{
this.self = this;
this.sectionId = sectionId;
this.resourceId = resourceId;
};
// member functions
this.doSetups = function()
{
console.log("SDSection doSetups: " + this.sectionId + "/" + this.resourceId);
};
});
TypedSectionHandler = new Class(SDSection, function(base, baseConstructor)
{
this.anotherId = -2;
// constructor
this.init = function(sectionId, resourceId, anotherId)
{
baseConstructor(sectionId, resourceId);
this.anotherId = anotherId;
};
// member functions
this.doSetups = function()
{
// call base function
base(this).doSetups();
console.log("TypedSectionHandler doSetups: " + this.anotherId);
};
});
var t = new TypedSectionHandler(1, 2, 3);
t.doSetups();
console.log(t instanceof TypedSectionHandler);
console.log(t instanceof SDSection);
Here's a working jsfiddle: http://jsfiddle.net/QYXSr/1/
Output:
SDSection doSetups: 1/2
TypedSectionHandler doSetups: 3
true
true
DISCLAIMER:
As I said, I'm the developer of this framework ;)
Ok I am definitely learning a lot when it comes to JavaScript scope functions and module patterns, awesome stuff! Right now I'm teaching myself to pass jQuery into a scope function this way it loads sooner, and if for some reason I had another framework that used $, there will be no confusion.
But what I don't fully understand is when to create a "new" instance "in context to scope functions" when I want to pass in jQuery. Here is what I mean...If I was going to use the following as a base, it will return pubs, which can be associated to a function or properties, etc, I get it.
var DemoA = (function($) {
var pubs = {};
pubs.dosomething = //some function that calculates cool stuff with help of jquery
return pubs;
})(jQuery);
Now when I try to create a new instance....
var stuff = new DemoA();
...I get an error through Google Chrome Developer Tools. It says "object is not a function" or something to that effect. But if I call DemoA directly like this...
DemoA.dosomething();
...then everything works fine. What is going on here? and why can't I create a new instance variable?
Thanks in advance for helping me get smarter!
Look at your return statement. You're returning an object that looks like this:
{"dosomething": function () { }}
You can't create a new instance of an object. You can call dosomething directly because it's an immediate property (method) of the returned object.
I think you want something like this:
http://jsfiddle.net/veJqg/
var DemoA = (function($) {
var pubs = function () {
this.dosomething = function () {
console.log("just executed `dosomething`");
};
};
return pubs;
})(jQuery);
var a = new DemoA();
a.dosomething();
This way, you are still aliasing the jQuery object as $, and you are returning a function that can be used in the way you want.
Just a bit more complex jQuery example which is commonly used:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
(function($) {
$.DemoA = function(element, options) {
var pubs = {};
return pubs;
}
$.fn.DemoA = function(options) {
return this.each(function() {
(new $.DemoA($(this), options));
});
};
})(jQuery);
var i = new $.DemoA(item, {});
var j = $('<div>').DemoA();
</script>
The code below is adapted from this answer
function MessageClass() {
var self = this;
this.clickHander = function(e) { self.someoneClickedMe = true; };
var _private = 0;
this.getPrivate = function() { return _private; };
this.setPrivate = function(val) { _private = val; };
}
ErrorMessageClass.prototype = new MessageClass();
function ErrorMessageClass() {
MessageClass.apply(this, arguments);
}
var errorA = new ErrorMessageClass();
var errorB = new ErrorMessageClass();
errorA.setPrivate('A');
errorB.setPrivate('B');
console.log(errorA.getPrivate());
console.log(errorB.getPrivate());
The original post did not have the MessageClass.apply(this, arguments); since the purpose was to show how inheritance can go wrong in Javascript.
My question is, is saying: ErrorMessageClass.prototype = new MessageClass(); before the ErrorMessageClass constructor has even been declared bad practice? My understanding is that calling undeclared identifiers like that causes a silent declaration to occur, with the result being placed on the global window object, which I understand is bad.
Is this form:
function ErrorMessageClass() {
MessageClass.apply(this, arguments);
}
ErrorMessageClass.prototype = new MessageClass();
considered to be better practice? This link shows the code written as it was originally above, which is why I even tried it. Does this blogger know something I don't (quite likely)?
EDIT
Lots of great info in the answers below, but I did want to highlight this link which really explains things perfectly
Usually, to avoid this confusion, you would just attach the prototype after, but as Adam Rackis pointed out, function declarations are hoisted, like var statements.
However, you should not instantiate the base object as the prototype. If your base object takes arguments, what are you supposed to use? Use an empty "surrogate" constructor
// Used to setup inheritance
function surrogate () {};
function MessageClass() {
var self = this;
this.clickHander = function(e) { self.someoneClickedMe = true; };
var _private = 0;
this.getPrivate = function() { return _private; };
this.setPrivate = function(val) { _private = val; };
}
// The key steps to creating clean inheritance
surrogate.prototype = MessageClass;
// Sets up inheritance without instantiating a base class object
ErrorMessageClass.prototype = new surrogate();
// Fix the constructor property
ErrorMessageClass.prototype.constructor = ErrorMessageClass
function ErrorMessageClass() {
MessageClass.apply(this, arguments);
}
There's much more to be said. http://js-bits.blogspot.com/2010/08/javascript-inheritance-done-right.html
It works because function declarations are evaluated first. If you tried to move these classes under an object literal "namespace" the first version would fail.
I personally find the second method to be much easier to read - also, don't forget to set the sub-class' prototype.constructor property back to itself. Personally, I use an inherits() method on the Function prototype which wraps up essentially the type of code you're using here.