MooTools get Classname in Class (not CSS)? - javascript

I'm using the JavaScript Framework MooTools in which it is possible to create classes similar to Object-Orientation.
I dont know if it is somehow possible to alert the classname 'TestClass' within the class.
var TestClass = new Class({
Extends: Module,
initialize: function() {
//constructor which is called and should alert the Classname itself
alert(this.classname); (pseudocode)
}
});
Someone has an idea?
Thx in advance!

This is pretty easy as a workaround but a Class can be anonymous (like a function) and reflection is meaningless then.
Compare the(a) host object's enumerables with the instance's constructor. Not a cheap thing but still. Won't work very well if you use deep namespaces, for example: window.App.admin.controllers.view.Login since you'd need to either recursively look for it or know it's hosted by window.App.admin.controllers.view
// define the class in the current scope / global object
this.foo = new Class();
// directly into scope
var Foo = new Class();
// define the class in a namespace
var namespace = {
bar: new Class()
};
// get the variable class name we need to use from any source into a variable...
var dynamic = 'foo';
// make the instances
var instance1 = new this[dynamic]();
var instance2 = new namespace.bar();
var instance3 = new Foo();
function getClassNameOfInstance(mootoolsClassInstance, context) {
// query the context (this or custom object) for the instance we are working with
return Object.keyOf(context || this, mootoolsClassInstance.constructor);
}
// use it on the global object
console.log("instance1 is: ", getClassNameOfInstance(instance1)); // foo
// use it on the namespace object
console.log("instance2 is: ", getClassNameOfInstance(instance2, namespace)); // foo
// use it on the current scope.
console.log("instance3 is: ", getClassNameOfInstance.call(this, instance3)); // Foo
see it work here: http://jsfiddle.net/dimitar/c8pR4/
here is an example anonymous Class, a useful pattern if you don't plan on instantiating something more than once:
var instance = new (new Class({ ... }))(args);
I did write about this a while ago - http://fragged.org/working-with-dynamic-class-names-in-mootools_1395.html
A better / more sensible approach will be to manually give IDs to all Classes that need them, eg:
var Request.CORS = new Class('Request.CORS', { ... });
var i = new Request.CORS();
i.$className; // 'Request.CORS'
this is a pattern common in AMD (define('id', [deps], fn)), DOJO (declare('id', [deps], obj)) etc.
To extend your MooTools to support that you could do something like this:
http://jsfiddle.net/rnbW6/5/ - which will add a Request.JSON.prototype.$className property or getter (via Object.defineProperty config if avail).
If you go that route, you can even do a Class factory so your dependency resolution can be like Class.require('Request.CORS') and you won't ever need to save your definitions into global variables outside of the reference in your Class closure.

Related

Javascript prototypes, how to access prototype functions

New to this whole concept of prototypes in Javascript and might be confused.
Let's say I have a class called Widget, defined as:
var Widget = function (options) {
// constructor code here
}
Widget.prototype.constructor = Widget;
Widget.prototype.myGreatFunction = function(){}
Should I be able to call Widget.myGreatFunction(); or do I need to call Widget.prototype.myGreatFunction()? to run the great function?
If you use your constructor function to make an instance, you can use the function from there:
var w = new Widget();
w.myGreatFunction();
You can also use the function by referring to it via the prototype:
Widget.prototype.myGreatFunction();
Ideal way of doing so is creating an instance and using the prototypal functions.
Nevertheless as the function is stored in Widget.prototype.myGreatFunction you can definitely access it.
The functions defined in the prototype are shared resources and thats the prime advantage of using it in this manner.
var Widget = function (options) {
// constructor code here
}
Widget.prototype.constructor = Widget;
Widget.prototype.myGreatFunction = function(i){console.log('myGreatFunction', i);};
var a = new Widget();
a.myGreatFunction(1);
var b = new Widget();
b.myGreatFunction(2);

How should I wrap up my engine?

I'm creating a game engine, or more like a large library of useful classes and functions, for Javascript. I plan to use it both for some scientific simulations on the server side and on the client side, so the spectrum of functionality will be quite broad, but always it will revolve around a virtual world (a game, for example).
I'm not sure how to wrap it up, though. If I just provide all the classes, it would pollute the global namespace, which is quite bad. Can I just place everything inside one object, that acts as a namespace? Should the framework itself be a class that can be instanced?
If the later option is chosen, how do I handle classes inside classes (constructor functions)?
var Engine = function()
{
this.someVar = 4;
}
Engine.prototype.Scene = function()
{
this.entities = [];
//What if the scene object needs some classes that are in the engine? How does it get it's parent engine object?
}
Engine.prototype.Scene.prototype.render = function()
{
//"this" should now represent an instance of a scene. But how can I get someVar from the engine? How can I traverse up in the hierarchy of classes?
}
I prefer to use what's sometimes called a "revealing module" (... pattern). It looks like:
var Engine = (function($)
{
$ = $ || {};
var someVar = 4;
$.Scene = function()
{
this.entities = [];
}
$.Scene.prototype.render = function()
{
// this function can access someVar just fine because of JavaScript's scoping rules
}
return $;
})(Engine);
This uses what's called an immediately-invoked function expression (hereafter referred to as an IIFE) to form a closure within the Engine object. Due to JavaScript's handling of scope, someVar is accessible to any function defined within the IIFE. The implication, however, is that no function can define it's own someVar if it wants to refer to the someVar you define in the IIFE.
The magic comes from the return statement. You can see that an object is returned, and within this object you must define anything you want to be "public".
The constructors, utility methods, etc. can then be accessed via Engine.Scene, which nicely namespaces your code.
As for the $ argument, this is so that you can pass Engine to the function in each file, add some methods/properties/constructors (or create a new one if it doesn't exist) and then pass the return value to another IIFE for further expansion.
This is the method used in many popular JavaScript frameworks including jQuery, dojo and LimeJS
scene.js:
var Engine = (function ($) {
// this creates a new object if Engine is undefined in the
// invocation below, and keeps the old object otherwise.
// alternatively: if ($ === undefined) { $ = new Object; }
$ = $ || {};
$.foo = "foo";
$.Scene = function () {
// blah blah
}
// Engine holds either a newly created object,
// or the old one if it was already defined
return $;
})(Engine);
sprite.js:
var Engine = (function ($) {
$ = $ || {};
$.Sprite = function () {
// totally works
this.bar = $.foo;
}
return $;
})(Engine);
You can then use them with something like:
<script type="text/javascript" src="bar.js"></script>
<script type="text/javascript" src="foo.js"></script>
<script type="text/javascript">
var mySprite = new Engine.Sprite;
var myScene = new Engine.Scene;
</script>
You can substitute $ with whatever you like, $$ is common, or you can be clever. It's just a placeholder for the global object you're adding on to.
I don't think you need or even should organize your classes like that. Even though the Scene and Engine classes are related, the Scene class doesn't have to be a children of Render. Use a flat class hierarchy instead, that will be easier to maintain and scale.
Finally, you should indeed put all these classes under the same namespace so as not to pollute the global namespace.
// Define the namespace only if it doesn't already exist. That
// way you can split the definition of your classes in various
// files, without having to worry in which order they are loaded.
if (typeof gameEngine === 'undefined') gameEngine = {};
gameEngine.Engine = function()
{
this.someVar = 4;
}
gameEngine.Scene = function()
{
this.entities = [];
}
// Add a new function to define which
// scene the Engine should render:
gameEngine.Engine.prototype.setScene = function(scene)
{
this.scene = scene;
}
gameEngine.Engine.prototype.render = function()
{
// render this.scene
}

Is it possible to add instance methods to all "classes" in JavaScript?

This is more of an exploratory question, seeing how the core JavaScript stuff works. I realize the convention is to not override any core JavaScript classes, but I just can't seem to wrap my head around this one.
You can create what acts like "class methods" in JavaScript by adding to the core Function prototype like this:
Function.prototype.class_method = function() {
console.log("class method called")
}
var User;
User = (function() {
function User() {}
return User;
})();
User.class_method(); // "class method called"
My question is, is there a way to add "instance methods" in a similar way? Something crazy like this, but what's below doesn't work (or make any sense):
alias = Function.prototype.constructor;
Function.prototype.constructor = function() {
child = this;
child.prototype.instance_method = function() {
console.log("instance method called");
}
alias.apply(child);
}
var user = new User();
user.instance_method(); // method doesn't exist
It's almost like you'd need to override the Function class' constructor method and access the prototype from there. Is this possible?
It does work if you add to the Object.prototype like this:
Object.prototype.instance_method = function() {
console.log("instance method");
}
var user = new User();
user.instance_method(); // "instance method called"
But that doesn't seem right either, mainly because seeing the output in the node.js console from console.log({}); change is confusing:
console.log({});
// {};
Object.prototype.instance_method = function() {
console.log("instance method");
}
console.log({});
// {"instance_method": [Function]}
If you are using node.js, you should be able to use Object.defineProperty [MDN] and make the new property non-enumerable:
Object.defineProperty(Object.prototype, 'instance_Method', {
value: function() {
console.log("instance method");
},
enumerable: false // it's already the default
});
This was introduced in ECMAScript5, so only newer browsers will support it.
It's important to understand when the prototype comes into play. It's simply an object that is a property of a function. It only has meaning when you use the new keyword. Example:
var Widget = function(val) {
this.value = val;
};
Widget.prototype.getValue = function() {
return this.value;
};
var widget1 = new Widget('test');
widget1.getValue(); // test
var widget2 = new Widget('test2');
widget2.getValue(); // test2
When new is used, the js interpreter will create a hidden _proto_ property on the instance. This proto link is simply a reference to the prototype object of the constructor function, e.g., Widget at the time the constructor was called.
When you override the Function constructor, you are literally adding something that will be on the _proto_ property of every function created after you modified Function.prototype.
If you make the statement child.prototype... = ... in your base 'class' constructor function, then that prototype will not have meaning until something 'instantiates' child, e.g., var child = new child();.
A great Resource.
To answer your question about 'instance methods', you simply need to do something like the following:
var Widget = function() {
this.method = function() {
return 'instance method';
};
};
Widget.prototype.method = function() {
return 'class method';
};
var widget1 = new Widget();
widget1.method(); // instance method
delete widget1.method;
widget1.method(); // class method
This is due to javascript's implementation of Prototypical Inheritance. The proto link I spoke of before is key here. When widget1 was first created, inside the constructor function Widget, method was attached specifically to widget1. This method will not be available to other instances. However, method on the prototype is shared across all instances of Widget.
At runtime, when the js interpreter sees widget1.method();, it first sees if widget1 has method as a property directly on it (objects in js are just hashmaps in essence, in which the keys are called 'properties'). It finds the instance method as a property in this case. However, once you delete the instance method, it will attempt to follow the _proto_ link, which is just an object reference to Widget.prototype (at the time the constructor was called). Widget.prototype.method is defined; therefore, the interpreter will execute that. If no method function is found when continuing to follow _proto_ links, it'll be a run-time error.

jQuery Pattern - is this valid or is there a better way?

I've sort if fell into this organization of javascript and was wondering if I'm missing the point somewhere here, or if there's a more elegant way of doing this.
Basically I'm wrapping everything in a function (object) and then setting up methods on that object, then instantiating an instance of the wrapper object and passing in any options and dependencies.
I have a hunch there's a way to automatically run .init() and a few other tweaks that could be made. Am I doing it right?
function AppModuleCore(){
var AppModuleCore = this; //keep internals sane
// Various global vars, objects
AppModuleCore.defaultOptions = {};
AppModuleCore.init = function(opts) {
// todo: that thing where you extend an options object a la juery
AppModuleCore.bindEvents();
};
AppModuleCore.bindEvents = function() {
// bind events here, send to functions within AppModuleCore.<FUNCTIONNAME>();
// Example:
$("a#clicker").unbind("click");
$("a#clicker").click(function(event){
AppModuleCore.handleClickerClick(event);
});
};
AppModuleCore.handleClickerClick = function(event){
alert("clicker was clicked");
};
}
// --------------------------------------------------------------------
// instantiate AppModuleCore object and initialize with opts,
// dependency injection
// --------------------------------------------------------------------
$(document).ready(function(){
AppModuleCore = new AppModuleCore;
var options = {};
AppModuleCore.init(options);
});
OK, some points
Having your code wrapped in a constructor only really makes sense if
You're going to instantiate more than one
You have "public" methods on the object that you are going to call
Your code doesn't exhibit these characteristics. I say this because your jQuery selectors a#clicker are hard coded so I'm assuming that you wouldn't want to bind the same events to them more than once?
You'd be better off using a function (perhaps your init) or an object literal to limit your scope..
function init( options ) {
var defaultsOptions = {};
var privateVar = 'only in this scope';
//extend your default options with options here
//using jquery
options = $.extend( defaultOptions, options );
// this function is completely private to this scope
function privatefunction() {
//do stuff
}
function handleClickerClick( event ){
alert("clicker was clicked");
}
// you don't need to wrap your handler in an anonymous function unless
// you're doing some work to the event before forwarding:- just give a
// reference to your handler
// the handler has access to other members of this scope, we're in a closure
$(options.selector).click( handleClickerClick );
//etc
}
init( {selector: 'a#clicker'} );
On a stylistic note: when you alias this with the same name as the constructor and then add methods to the alias, it looks at first glance like you are adding static methods to the constructor. This may be confusing to someone who looks at your code later and doesn't notice the alias.
function C() {
// a static method i.e a property of the constructor, C not objects created with it
// it is a bit wierd that it is defined in the constructor but not unheard of
C.staticMethod = function(){};
//quite plainly a method of objects of this type, easy to understand
this.method = function(){};
}

Javascript plugin creation

I want to create a plugin called 'myPlugin'. Which method should I use and what is the difference between these two methods? Please tell me the advantages too. I am from designing background and not much programming knowledge.
var myPlugin = {
myId:"testId",
create:function(){},
destroy:function(){}
}
OR
function myPlugin() {
this.myId = "testId";
this.create = function(){};
this.destroy = function(){};
}
The first method creates a singleton object, stored in a variable called myPlugin. Only one instance of the "plugin" exists in this form. If you know you will only need one instance, this approach is a good choice. You can also extend its capabilities to allow for both public and "private" properties by using the Module Pattern.
The second method defines an object constructor function, which will allow you to make multiple instances of the object using the new keyword. This will allow you to use as many copies of the object as you might need, and sets you up with the ability to add onto the object using its prototype.
I would go for something like:
function myPlugin () {
this.myId = "testId";
this.create = createFunction;
this.destroy = destroyFunction;
}
function createFunction() {
alert('createFunction() called');
}
function destryFunction() {
alert('destroyFunction() called');
}
my plugin = new myPlugin();

Categories