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

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.

Related

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

Change private class methods

I am attempting to change the behavior of a jquery plugin without actually changing the source. For the purposes of this question, I constructed a simple example that illustrates my problem. If a have script file that attaches a class instance generator to a global variable like this:
(function(){
window.newMyClass = function(){
return new myclass();
}
function myclass(){
var privateMethod = function(){
return "private";
}
this.publicMethod = function(){
return privateMethod();
}
}
})()
If I then get new instance of myclass with var instance = window.newMyClass(), is there any way to override the behavior of privateMethod on instance, such that instance.publicMethod() would call my overridden function? I was thinking I could subclass myclass, but since the myclass constructor is scoped to the immediately invoked function expression, I don't know how to do that.
Is it better just to change the plugin source? The problem with that is I'd have to host it myself instead of using a CDN, as well as re-implement the change every time an update is released.
I don't know if I understood well this. Probably not, because there is no mistery with that:
(function(){
window.newMyClass = function(){
return new myclass()
}
function myclass(){
var privateMethod = function(){
return "private";
}
this.publicMethod = function(){
return privateMethod();
}
}
})();
var instance = window.newMyClass();
instance.publicMethod = function(){
return "new method";
}
console.log(instance.publicMethod());
FIDDLE: http://jsfiddle.net/r9evbzd2/1/

Cleanest way to write prototype inheritance in JS

Somewhat of a JS newbie still, I'm trying to understand the best / cleanest way to use prototypes and inheritance.
Normally I write object/prototype definitions like this:
var Foo = function(data) {
this.data = data;
};
Foo.prototype = {
someMethod: function() {
return "whatever";
}
};
I like this because I often am using namespace objects a few layers deep, so it might actually look more like this:
App.Model.FooModel = function(){...};
App.Model.FooModel.prototype = {...};
This is nice because I don't have to type out the full name of every method to write the prototype, just the name, ie. someMethod: function(){} instead of App.Model.FooModel.prototype.someMethod = function(){}.
Now, the problem I've run into is I'm not sure how to do this with inheritance in JS. I can get inheritance working fine if I do it like this:
var Child = function(){...};
Child.prototype = new Parent;
Child.prototype.someMethod = function(){...};
...but now in a more complicated application we're back to writing out the full name of the object for every method, which I find both tedious and hard to read.
So, my question is: is there a clean, straightforward way to write prototypes that inherit from another object, except to attach all child methods using the full name of the object?
Thanks!
Well, this being javascript, you can always write your own:
function construct ( parent, fn, attr ) {
fn.prototype = new parent();
for (var x in attr) {
fn.prototype[x] = attr[x];
}
return fn;
}
You can do the hasOwnProperty check if you want but the above is simplest implementation for clarity. This function encapsulates the three steps into one. You can now simply do:
var Foo = construct(
Parent,
function(data) {
this.data = data;
},
{
someMethod: function() {
return "whatever";
}
}
);
If you don't like the syntax you can always come up with a better one. An alternative implementation is to simply implement the attr extension part and do the inheritance normally:
function extend (obj, attr) {
for (var x in attr) {
obj.prototype[x] = attr[x];
}
return obj;
}
Again, simplified for clarity. So the syntax now becomes:
var Foo = function(){...};
Foo.prototype = new Parent;
extend(Foo.prototype,{
someMethod : function(){...}
});

javascript prototyping explain [duplicate]

I normally in my project create my class in this way... Object literal.
var objectName = {
//global variables
a : 'somevalue',
func1: function(){
},
func2: function(){
}
}
If i have to turn this into prototype format, how would I do that?
What would be my advantage of using prototype than this one, when the job is getting done with this format.
Why do people speak so much on prototype.
Turned into a prototype would look something like:
var someObject = function() {
this.a = "somevalue";
};
someObject.prototype.func1 = function() { // work };
someObject.prototype.func2 = function() { // work };
var myObject = new someObject();
What are some advantages? Well, there are a bunch, but there
are a handful really practical reasons when prototypes make
more sense than object literals.
First is reduction of duplicated code; So, lets say you wanted
another object very smiliar to objectName, but you wanted a to
be a different value. You would probably end up with something like:
var objectName = {
a : 'somevalue',
func1: function(){ },
func2: function(){ }
}
var otherObjectName = {
a : 'otherValue',
func1: function(){ },
func2: function(){ }
}
And you could reduce the duplicated functions by saying
var objectName = {
a : 'somevalue',
func1: function(){ },
func2: function(){ }
}
var otherObjectName = {
a : 'otherValue',
func1: objectName.func1,
func2: objectName.func2
}
Or, using a prototype, I could just make it so I could pass in the value I want for a in during the construction of the object. The refactored code would look something like this:
var someObject = function(a) {
this.a = a;
};
someObject.prototype.func1 = function() { /* work */ };
someObject.prototype.func2 = function() { /* work */ };
var myObject = new someObject("somevalue");
var myOtherObject = new someObject("otherValue");
Now, if i wanted to add a new function to both of them. Using the object literal apporach, then you would have to remember to also add it to otherObjectName. As the number of your literals increased, it would take longer and more difficult to manage them all.
Using the prototype approach, all we would have to say is:
someObject.prototype.func3 = function() { // do even more work }
or even more interesting i could dynamically extend both object by only
having a reference to one by saying.
// find what function made me, get its prototype, and add a new function to it
myObject.constructor.prototype.func3 = function() { /* work */ }
myOtherObject.func3() // tada magic!
or I could make a new object, by only knowing a reference. like:
var newObject = myObject.constructor(myObject.a + " new");
Because both myObject and myOtherObject share the same constructor and prototype, there are a lot of interesting things
you can do with that relationship that you can't do with object literals.
You can think of prototypes as little factories to create objects
rather than having to create every object yourself as a literal.
Now, if you are thinking, "Well, I'm only going to have one
of these and I'm not going to be doing any of your crazy method
extending magic." Then defining an object literals is a perfectly valid apporach
for some problems. Sometimes using a prototype is better. Use the
pattern that makes sense for the problem that you are trying to solve,
rather than trying to fit your problem into a pattern.

Returning the method of a function

In the code below, I've got two objects declared, with one object inheriting the properties and functions of another.
I want to use the super variable to call the methods of the object I inherited from. When I trace out itemEditor, I can see the function and it's methods correctly. When I try to access the method of itemEditor, it returns undefined.
What am I doing wrong? Is there a better way to do this?
var myObject = {
itemEditor : function (vars) {
this.editItem = function () {
alert("Editing Item");
}
},
recurringItemEditor : function (vars) {
myObject .itemEditor.apply(this, [vars]);
this.prototype = myObject.itemEditor.prototype;
var super = myObject.itemEditor
this.editItem = function () {
console.log("fn.recurringItemEditor.editItem");
console.log(super);
console.log(super.editItem);
super.editItem.call(this);
}
}
Your code seems a little confused. On the one hand myObject.itemEditor is a constructor and therefore a function (myObject.itemEditor.apply(this, [vars])), and on the other you treat it like an object with a prototype (this.prototype = myObject.itemEditor.prototype;).
That's not even considering that super is a reserved keyword.
Your example may be simplifying something you are trying to do, but I don't see why you don't just use the usual prototype inheritance. That way you can still have a method in your local instance and call the prototype one within it if you want e.g.
recurringItemEditor : function (vars) {
this.prototype = new myObject.itemEditor(vars);
this.editItem = function () {
console.log("fn.recurringItemEditor.editItem");
console.log(this.prototype);
console.log(this.prototype.editItem);
this.prototype.editItem.call(this);
}
}
I used your advice and it works well now. In regards to treating it like a function and an object, myObject .itemEditor.apply(this, [vars]); was still required in order for the object to inherit the properties of itemEditor. I should have made that clear in the original code. If there's a better way to do this, let me know.
var myObject = {
itemEditor : function (vars) {
var myVars = vars + "foo";
this.editItem = function () {
alert(myVars);
}
},
recurringItemEditor : function (vars) {
myObject .itemEditor.apply(this, [vars]);
this.prototype = new myObject.itemEditor(vars);
this.editItem = function () {
console.log("fn.recurringItemEditor.editItem");
console.log(this.prototype);
console.log(this.prototype.editItem);
this.prototype.editItem.call(this);
}
}
}

Categories

Resources