Understanding New with JavaScript scope functions and passing $ - javascript

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>

Related

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();
});

Best way to implement jquery scoping on object classes?

In jQuery, I would like to define objects which act as classes (having private and public methods/properties). But also having a way to define a scope to that object. To illustrate, consider this pseudocode:
var myclass = function(context) {
$.setscope(context); // <-- this is not real, but I want something like this
this.getItems = function() {
return $('.grid'); // after calling `setscope` above, this will look in the scope of #page1
};
}
var myclass_instance = new myclass("#page1");
Basically what this does, it forces jQuery to automatically use the scope of #page1 when ever I 'select' something from within myclass_instance. All code in it (public or private) should automatically use that scope. In other words, I shouldn't have to do return $('#page1').find('.grid');.
What I have now is a var context = '#page'; defined on top, and then $(context).find(... everywhere in the class. This seems kinda redundant.
Does anyone know if this is possible, and if not, the best way to implement this?
Maybe something like this?
function myClass(context) {
var _$ = $,
$ = function() {
return _$.find(context).apply(this, Array.prototype.slice.call(arguments));
};
this.getItems = function() { return $('.grid'); }
}
It's sounds like it's pretty simple abstraction you're looking for. Just define a method on MyClass that always queries the dom in the scope that you set on instantiation:
var MyClass = function(scope) {
this.scope = scope;
};
MyClass.prototype.get = function(selector) {
return $(selector,this.scope);
}
MyClass.doStuff = function() {
var $el = this.get('#someid');
//do some stuff with $el;
}
var o = new MyClass('#scope');

Extending a function and instantiating it - javascript

--
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();

Is there a way to instantiate this class with dot syntax?

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.

Javascript inheritance misbehaviour

I have some js code here link deleted
If you open your js console and you'll run this code snipet
var r = new TempPopupForm("xxx");
r.create();
an error will appear
TypeError: this.init is not a function
this error is saying there is no init method implemented on this object.
But that's not true.As you can see in the code below the init method is declared.
TempPopupForm.prototype = new PopupForm();
TempPopupForm.prototype.constructor = TempPopupForm;
TempPopupForm.superclass = PopupForm.prototype;
function TempPopupForm(name) {
this.init(name);
}
TempPopupForm.prototype.init = function(name) {
TempPopupForm.superclass.init.call(this, name);
};
I guess something is wrong with the inheritance definition,but I can not figure out what it is.
BTW There are some third party dependencies.
EDIT
I was following this article and where the funcs are ordered like I have. The order actually works on the other classes, but not on this one.
http://www.kevlindev.com/tutorials/javascript/inheritance/inheritance10.htm
You need to re-order your functions and instantiation. Since your constructor is using one of its own prototyped method to init, they both need to be above the block where you instantiate the object. JavaScript hoists top-level functions.
Try this -
function TempPopupForm(name) {
this.init(name);
}
TempPopupForm.prototype = new PopupForm();
TempPopupForm.prototype.constructor = TempPopupForm;
TempPopupForm.superclass = PopupForm.prototype;
TempPopupForm.prototype.init = function(name) {
TempPopupForm.superclass.init.call(this, name);
};
var r = new TempPopupForm("xxx");
r.create();

Categories

Resources