organizing js prototype methods - javascript

after experimenting with js's prototypal inheritance i've found that i'm not wild about the idea of having to declare my object's methods outside of the object:
function obj(){
this.averyday='i\'m shuffle\'n';
this.gibmo='dinero';
this.pullOut='that\'s what she said lol';
}
obj.prototype.alertProp=function(){
alert(this.averyday);
}
obj.prototype.alertProp2=function(){
alert(this.gibmo);
}
so i came up with a way to organize my methods into one namespace
obj.prototype.m={
//i'm passing in the object instance so the mathods can have access to it's properties
alertProp:function(that){
alert(that.theObj.everyday);
},
alertProp2:function(that){
alert(that.myObj.gibmo+' '+that.myObj.someVal); // alerts "dinero some other value to be use "
}
}
var myobj = new obj;
then to use i just call the method and pass in the objects instance(if the method needs to modify the object's properties)
myobj.m.alertProp({theObj:myobj,someVal:'some other value to be use'}) //alerts "i'm shuffle'n"
so here are some pros that i've noticed:
PROS:
1) organizes the methods into one centralized area.
2) accesses the "prototype" of an object only once(in effect uses less code).
3) seems more readable(at lease to me).
CONS:...this is where i need you'alls help, does anyone see anything wrong with doing it this way? any performance issues or anything wrong with the pros i've outlined etc...?
also does anyone see any other pros that i may not be seeing or that aren't apparent?

I find it a little bit complicated, this is how I like to do it:
MyObject = function (options) {
this.init(options);
};
MyObject.prototype = {
/**
* Documentation
*/
variable1: null,
init: function (options) {
// do something with options.
},
alertVariable: function () {
alert(this.variable1);
}
};
So you don't have to worry about sending extra parameters, you just call it.
----------------------------EDIT---------------------------------
Well, I don't know if I got it right, but after some reading I believe this would "fixing the constructor" mean. If I create an object like this:
Foo = function () {
// Do something
};
Then Foo.prototype.constructor == Foo, as one would expect.
The problem with my method (thanks Raynos) is that when I'm doing this:
Foo.prototype = {...};
I'm overwriting all of Foo's prototype, so that Foo.property.constructor != Foo, and that is not what we would expect! Instead of that we have that Foo.property.constructor == Object.prototype.constructor.
So, how we fix it?
Foo.prototype = {
constructor: Foo, // <-- FIXED!
...
};
Ta da!
(this helped a lot: http://beej.us/blog/data/javascript-prototypes-inheritance/ )

Related

Is there any difference between these three ways of declaring methods in JS?

Say I have a type called MyObject and I want to add the method myMethod to it. Is there any difference (logically, but also performance-wise) between the following ways?
#1
function MyObject() {
...
}
MyObject.prototype.myMethod = function() {
...
};
#2
function MyObject() {
this.myMethod = function() {
...
};
...
}
#3
function MyObject() {
this.myMethod = myMethod;
...
}
function myMethod() {
...
}
I wouldn't mind knowing if there's a performance difference - e.g. if way #2 is costly because it defines the function separately every time an object is instantiated - but I'm mostly concerned with whether the results are equivalent.
In addition, with method #2, isn't this the same way that a class-level/static method would be defined, so does it have the danger of being called like MyObject.myMethod();? If myMethod used this and it was called on MyObject rather than an instance of MyObject, I would think this would cause issues. So does the compiler/interpreter check to see whether this is present or would it throw an error?
#1: This is the preferred way to write "class-level" methods. This saves on memory (as you'll see in #2) and JS engines can know that each instance will have this method and optimize around that.
#2: You're right, this one is more costly because it creates a new function for each instance. The difference here is that you can include private variables generated in the constructor. For example:
function MyObject() {
var name = 'Me';
this.getName = function() {
return name;
};
}
Only things created in the constructor will have access to name.
#3: This approach is largely the same as #1 but I imagine that JavaScript engines are not written to optimize for this case (but this might not be true and may change, JS engines are constantly evolving). This also creates a global function (assuming you're not using a module system) which can create major issues later.
Option 1: You can call my method without instantiating MyObject:
MyObject.prototype.myMethod();
Options 2: You must instantiate the MyObject to be able to access myMethod.
This will fail:
MyObject2.myMethod();
Uncaught TypeError: undefined is not a function
This will not:
var myObject = new MyObject2();
myObject.myMethod();
Check out the code pen: http://codepen.io/sessa/pen/tfqln

Simple way to access current object

I'm trying to find a simple way to refer to the current instance of an object from the object methods itself (similar to this keyword in any decent language).
I've tried many variations of "storing a pointer for itself" (like window.window.window do), but always something go wrong. For example:
function ClassA() {
var mySelf = this;
this.myMethod = function() {
console.log(mySelf); //Once you extend this class, mySelf will not be available
}
}
function ClassB() {
this.mySelf = this; //Ok, now you can extend this and mySelf will be there
this.myMethod = function() {
console.log(mySelf);//"mySelf is not defined" because it's a property now
console.log(this.mySelf);//Value of 'this' and 'self' will vary
console.log(RandomContainer.ClassBInstance.mySelf);//I can't use a defined path
}
}
Since everything about OOP in JavaScript is hackish, I have to ask...
Is there any magic to refer to the current object that a method is being called from?
EDIT
A lot of possible solutions in the comments, thanks guys!
But I still need to improve my question. So I'll add some piece of code with my failed attempts, and then try out the proposed solutions...
function BaseController()
{
var myPriv = 42;
return {
getAnswer: function() {
return myPriv;
}
};
}
function SomeController()
{
return {
showAnswer: function()
{
var answer;
answer = myPriv; //I need some way to access this
answer = getAnswer(); //Also a way to refer to my own methods
//(I don't even find a way to call 'showAnswer' from this context)
console.log('The answer is ' + answer);
}
};
}
//That's how I was extending my classes so far...
var someControllerInstance = jQuery.extend(
new BaseController(),
new SomeController()
);
someControllerInstance.getAnswer(); //Works!
someControllerInstance.showAnswer(); //Reference errors...
take time to learn the idiosyncrasies of js, be warned though, it's like marmite.
If you'll allow me to be blunt for a moment, you are approaching JavaScript with the wrong frame of mind. It is not designed for classical inheritance, nor for protected properties or methods, and there is no benefit in bending it that way. To be honest I find towering stacks of inheritance a pain to read and navigate, unless you have a singing-all-dancing IDE that may take a week to load. The closer to flat and open you can achieve — whilst still keeping things flexible — the better you are at coding, and the more other coders that may take over your work will thank you. (obviously that is opinion)
For more information on prototype inheritance read the following informative post:
http://davidwalsh.name/javascript-objects-deconstruction
Below is an example of prototype inheritance, it should be noted that Object.create and isPrototypeOf are relatively new and do not exist for older JavaScript interpreters. Approximate polyfills can be used in most cases however.
Put simply JavaScript becomes much more powerful when you think in terms of objects borrowing methods from wherever they may be found, and not instances rigidly inheriting from slightly less specific instances; or worse, constructors that keep rebuilding the same functions again and again.
The following is just an example, and across my 16 years of coding ECMAScript I have barely ever needed anything that approaches classical inheritance, nor have I needed objects that heavily inherit on the prototype chain either. More often than not my js is basically just a number of newly created objects, properly name-spaced, that borrow methods from fixed pools of functions; any type detections are duck-typed, and I'm careful to keep everything as local as possible.
Anyway, here's something I don't often use:
var Make = function(construct){
return Object.create(construct);
};
var Extend = function(proto, props){
var instance = Object.create(proto);
for ( var i in props ) { instance[i] = props[i]; }
instance.super = proto; // this should never be needed really
return instance;
};
var Animal = {
keepBreathing: function(){
console.log('animal', this);
}
};
var Monkey = Extend(Animal, {
climbTree: function(){
console.log('monkey', this);
console.log('monkey', this.super);
}
});
var KeyserSoze = Make(Monkey);
KeyserSoze.keepBreathing(); /// animal, instance of KeyserSoze
KeyserSoze.climbTree(); /// monkey, instance of KeyserSoze
console.log('an instance of monkey', KeyserSoze);
console.log('has animal as proto', Animal.isPrototypeOf(KeyserSoze)); // true
console.log('has monkey as proto', Monkey.isPrototypeOf(KeyserSoze)); // true
Whilst the above does follow a kind of classical layout i.e. Monkey inherits methods from Animal, you could approach things in a different way. The following is more open to dynamic changes, in the fact you could switch out the behaviours object for another interface entirely. Again, this is just an illustration that you don't have to construct things in a fixed way.
Something I'm more likely to use:
var AnimalBehaviours = {
keepBreathing: function(){
(this.breathCount === undefined) && (this.breathCount = 0);
this.breathCount++;
}
};
var ApeLikeDescendant = (function( behaviours ){
return {
create: function( config ){
return Object.create(this).prep(config);
},
prep: function( config ){
/// do your instance specific set up here
return this;
},
climbTree: function(){
console.log('ape-like', this);
},
keepBreathing: function(){
return behaviours.keepBreathing.apply(this, arguments);
},
switchBehaviours: function(newBehaviours){
behaviours = newBehaviours;
}
};
})(AnimalBehaviours);
var DouglasAdams = ApeLikeDescendant.create({});
You could adapt the above to behave more in a manner similar to mixins i.e. you'd take the behaviours, step through them and merge them to the ApeLike object... it's really quite open to whatever your goal is.
Something that I use regularly:
var ElementEdgeCases = {
makeWorkOnNetscape47: function(){
this.target; /// Intentionally left almost blank.
}
};
var ElementFinagler = (function(){
var finagle = {
target: null,
prep: function( element ){
this.target = element;
return this;
},
addClass: function(){
var c = this.target.getAttribute('className'); /// and so on ...
return this;
},
elaborate: function( mixin ){
for ( var i in mixin ) {
if ( mixin.hasOwnProperty(i) ) {
this[i] = mixin[i];
}
}
return this;
}
};
return function( element ){
return Object.create(finagle).prep(element);
};
})();
var elm = document.getElementsByTagName('body')[0];
ElementFinagler(elm)
.elaborate(ElementEdgeCases) // extend the object if we need
.addClass('hello world')
;
The main thing to keep in mind with JavaScript is that no function is owned by anything, not really. Every time you execute a function, the function's context is implied by the way you call that function — the context is computed at call time. This allows a great deal of flexibility, and whilst you mention that calling function.apply(context, args) or function.call(context, arg, arg, ...) every time is cumbersome; it is very easy to codify your own system for hiding that repetition away.
Oh, and before I forget, one other thing to take away from the code above is that there is no duplication of function creation. Every instance shares the same functions in memory. This is an important thing to bear in mind if you are planning to create large scale applications, as you can quickly eat up memory with multiple instances of functions.
So just to recap:
Forget inheritance, it's rarely required for many js projects.
Create flexible objects that can be extended when required.
Borrow methods when you need them from other objects, using apply or call to change context.
Keep your code open, there is no need for private; open is more extensible.
Private no, but having properties not enumerable is a different story, see defineProperty.
Make sure you do not duplicate functions — unless you have to — instead create them once and reference.
this referrers to the dom node that an event originated from, or the javascript object it is a child of. In that order.
this.parentNode referrers the dom node's parent (Not sure if it works in object context).
When I write javascript I'll usually try to leverage the html's dom itself, nesting things mindful of how the JS needs to reference them.

Creating a Javascript Object Which Does Nothing

As a somewhat hacky method of disabling functionality, I came up with the idea of using some javascript like this:
//fakefrob.js
var frob = function () {
return {
myFunc: function(){},
myFunc1: function(){},
myFunc2: function(){return 2;},
myFunc3: function(){},
myFunc4: function(){}
};
}();
In this example, the real frob has implementations of these functions. Obviously this is a hack (the functions mostly do nothing or have placeholder return values). If I add foobar to realfrob.js, I must add an empty implementation of foobar to fakefrob.js. Is there a way (ideally without using a library) to write fakefrob.js such that frob.foobar acts like foobar was defined as function(){};, without actually adding foobar to fakefrob.js?
Is there a way (ideally without using a library) to write fakefrob.js such that frob.foobar acts like foobar was defined as function(){};, without actually adding foobar to fakefrob.js?
You mean, a catch-all property, mapped to a no-op function? No, JavaScript doesn't (currently) have catch-all properties at all. (I believe some mechanism for them is being considered, as part of the proxy stuff coming down the pike at some stage.)
If you have access to the real frob in your code, though, your fakefrob can be generated completely automatically:
// Assumes `frob` already exists
(function() {
var mock;
var name;
// Build the mock, with a function for each function
// on the real object.
mock = {};
for (name in frob) {
if (typeof frob[name] === "function") {
mock[name] = function() { };
}
}
// Replace the original
frob = mock;
})();
And of course, if you wanted to copy the non-function properties, you could do that at the same time.
Note that I intentionally did not include hasOwnProperty in the loop above, as I assume you want your mock to include functions even if frob inherits them from a prototype.
If frob inherits some functions and you wanted your mock to exhibit the same hasOwnPropety behavior for them as the original frob, you can get more creative:
// Assumes `frob` already exists
(function() {
var mock;
var mockProto;
var name;
function FakeFrob() {
}
mockProto = FakeFrob.prototype;
// Build the mock, with a function for each function
// on the real object.
mock = new FakeFrob();
for (name in frob) {
if (typeof frob[name] === "function") {
if (frob.hasOwnProperty(name)) {
mock[name] = function() { };
}
else {
mockProto[name] = function() { };
}
}
}
// Replace the original
frob = mock;
})();
Now, if the original frob had its own foo (frob.hasOwnProperty("foo") is true) but an inherited bar (frob.hasOwnProperty("bar") is false), hasOwnProperty on your mock would say exactly the same thing.
As T.J. Crowder suggests, supported browsers can use a proxy object to accomplish this:
var frob = new Proxy({}, {get: function(){return function(){}}})
How this works:
This creates a proxy which intercepts all property getters, replacing the result with an empty function. Normally, a proxy object is used to to intercept and eventually forward calls to our target (here, the target is {}). However, this code blindly returning an empty function, completely ignoring the target.

Is there a way to catch an attempt to access a non existant property or method?

For instance this code:
function stuff() {
this.onlyMethod = function () {
return something;
}
}
// some error is thrown
stuff().nonExistant();
Is there a way to do something like PHP's __call as a fallback from inside the object?
function stuff() {
this.onlyMethod = function () {
return something;
}
// "catcher" function
this.__call__ = function (name, params) {
alert(name + " can't be called.");
}
}
// would then raise the alert "nonExistant can't be called".
stuff().nonExistant();
Maybe I'll explain a bit more what I'm doing.
The object contains another object, which has methods that should be accessible directly through this object. But those methods are different for each object, so I can't just route them, i need to be able to call them dynamically.
I know I could just make the object inside it a property of the main object stuff.obj.existant(), but I'm just wondering if I could avoid it, since the main object is sort of a wrapper that just adds some functionality temporarily (and makes it easier to access the object at the same time).
Well, it seems that with harmony (ES6), there will be a way, and it's more complicated compared to the way other programing languages do it. Basically, it involves using the Proxy built-in object to create a wrapper on the object, and modify the way default behavior its implemented on it:
obj = new Proxy({},
{ get : function(target, prop)
{
if(target[prop] === undefined)
return function() {
console.log('an otherwise undefined function!!');
};
else
return target[prop];
}
});
obj.f() ///'an otherwise undefined function!!'
obj.l = function() {console.log(45);};
obj.l(); ///45
The Proxy will forward all methods not handled by handlers into the normal object. So it will be like if it wasn't there, and from proxy you can modify the target. There are also more handlers, even some to modify the prototype getting, and setters for any property access yes!.
As you would imagine, this isn't supported in all browsers right now, but in Firefox you can play with the Proxy interface quite easy, just go to the MDN docs
It would make me happier if the managed to add some syntactic sugar on this, but anyway, its nice to have this kind of power in an already powerful language. Have a nice day! :)
PD: I didn't copy rosettacode js entry, I updated it.
There is a way to define a generic handler for calls on non-existant methods, but it is non-standard. Checkout the noSuchMethod for Firefox. Will let you route calls to undefined methods dynamically. Seems like v8 is also getting support for it.
To use it, define this method on any object:
var a = {};
a.__noSuchMethod__ = function(name, args) {
console.log("method %s does not exist", name);
};
a.doSomething(); // logs "method doSomething does not exist"
However, if you want a cross-browser method, then simple try-catch blocks if the way to go:
try {
a.doSomething();
}
catch(e) {
// do something
}
If you don't want to write try-catch throughout the code, then you could add a wrapper to the main object through which all function calls are routed.
function main() {
this.call = function(name, args) {
if(this[name] && typeof this[name] == 'function') {
this[name].call(args);
}
else {
// handle non-existant method
}
},
this.a = function() {
alert("a");
}
}
var object = new main();
object.call('a') // alerts "a"
object.call('garbage') // goes into error-handling code
It seems that you know your way around JS.
Unfortunately, I don't know of such feature in the language, and am pretty sure that it does not exist. Your best option, in my opinion is either using a uniform interface and extend it, or extend the prototypes from which your objects inherit (then you can use instanceof before going forward with the method call) or use the somewhat cumbersome '&&' operator in order to avoid the access of nonexistent properties/methods:
obj.methodName && obj.methodName(art1,arg2,...);
You can also extend the Object prototype with Anurag's suggestion ('call').
You can also check if the method exists.
if(a['your_method_that_doesnt_exist']===undefined){
//method doesn't exist
}

Ok, we can have private identifiers in javascript, but what about protected ones?

Simple as that, can we emulate the "protected" visibility in Javascript somehow?
Do this:
/* Note: Do not break/touch this object */
...code...
Or a bit of google found this on the first page:
http://blog.blanquera.com/2009/03/javascript-protected-methods-and.html
Sure you can. Here's another example.
What could that possibly mean? You don't have classes.
I suppose you could analyze caller to determine whether it meets some set of criteria for being permitted to call a method. This will be hideously inefficient and your criteria will always be spoofable.
There's an interesting pattern worth mentioning here: a JavaScript contructor function may return any object (not necesserily this). One could create a constructor function, that returns a proxy object, that contains proxy methods to the "real" methods of the "real" instance object. This may sound complicated, but it is not; here is a code snippet:
var MyClass = function() {
var instanceObj = this;
var proxyObj = {
myPublicMethod: function() {
return instanceObj.myPublicMethod.apply(instanceObj, arguments);
}
}
return proxyObj;
};
MyClass.prototype = {
_myPrivateMethod: function() {
...
},
myPublicMethod: function() {
...
}
};
The nice thing is that the proxy creation can be automated, if we define a convention for naming the protected methods. I created a little library that does exactly this: http://idya.github.com/oolib/

Categories

Resources