8 posts tagged “javascript”
This one's going to be short.
:name"name"function $(name){$nameI recently discovered this thing called Functional Javascript, which contains a number of quite sexy modifications to Javascript's base classes to add extra, more functional things. While I was browsing Oliver Steel's blog, I came across his Javascript memoizer.
foo.bar = function(){ ... }foo.bar = function(){ ... }.memoize();x = function(){ ... }.method();function(){ ... }. method();function(){ ... }(function(){ ... })Ok, so for a while now I've been woefully undereducated on the uses of try...catch. I know, I know, how can I claim to know JavaScript beyond even a basic level without knowing try...catch. Ok fine, sue me, denounce me as a poser, MEA CULPA. :P
Why is this relevant to the title? Well for a while now I've been manually checking argument type like so:
function doSomething( aJadeObject ){
if( aJadeObject == undefined ){ return; }
if( typeof(aJadeObject.isKindOfClass) != "function" ){ return; }
if( !aJadeObject.isKindOfClass(NecessaryClass) ){ return; }
//blah blah blah...
}
The first line verifies that the argument is defined, because if it's not the second line will destroy the script. The second verifies that the object responds to the JadeObject method that's used to test descent from a particular class. The third actually verifies that descent. I did this for obvious type-checking purposes. I don't want to sent JadeArray query messages to a number or to null and kill the program, do it? No. Instead it would be better if bad messages just returned some default or null value or something, so that in such a case, the program would still function but there would just be a minor, localized, and likely unnoticeable, fault, instead of taking the entire thing down.
This whole convoluted system came up in a discussion with the ever patient Emmanuel Zephyr, my Cocoa devver friend person. I asked him his opinion on what sort of values should be returned when the function by default is supposed to return some none-void value. His suggestion was that i shouldn't even bother with all of that but instead should just use try...catch, which would simply try to perform the necessary operations without crashing the script. If the objects in question respond to the necessary messages then the try block will work successfully, which means that as far as the script cares, the arguments were the right type, otherwise it would fail and no bad things would happen.
So instead of all of that junk above, it would reduce to...
function doSomething( aJadeObject ){
try {
//blah blah blah...
} catch(e){
//maybe log the error?
}
}
without any type checking at all, and with a potential area for handling these type errors, possibly with some sort of logging for later debugging. I can't really believe that I allowed such a useful tool as try...catch slip past my dradis, but that's life, ey?
My only concern is this:
var x = 0;
try {
x = 5;
y++; // throws an exception because y is undefined
}
alert(x); // alerts 5, because the x = 5 assignment works, despite the try block containing exception-throwing code.
This is potentially problematic because there might be cases where something is added to an array or whatever on the assumption that it's a certain type of object, and then it gets sent a message that it doesn't know how to respond to because it's not that type of object. So now the try fails but the object is still in the array, which is probably not a good thing. Now, this might not be a huge issue, and any problems that it might cause probably won't be too hard to fix, but it's definitely not perfect. Oh JS2, where art thou?
No, not the bastard lovechild of Superman and Crystal Method.. Super methods are methods that belong to the class that's being inherited from. It's possible to retail these methods even after they've been re-defined, by providing a nice new method to the Object class prototype.
What we'll do is create a convenience method that will take care of the inheritance for us, and include a little bit of code to make super methods available:
Object.prototype.extend = function( Class ){
Class.apply(this);
var supers = {}; // not "super" because that's a reserved keyword in JS
supers.constructor = this.constructor;
for( var m in prototypical ){
supers[m] = this[m];
}
this.supers = function(){
var dupe = {};
for( var m in supers ){
dupe[m] = supers[m];
}
return dupe; // use private variables and a duplicate to prevent destruction of the original supers object
}
}
With this, we can now extend other classes while retaining the ability to utilize their methods if needed:
function A(){
var foo = "bar";
this.getFoo = function(){ return foo; }
}
function B(){
this.extend(A);
var baz = "bop";
this.getFoo = function(){ return baz; }
}
var b = new B;
alert( b.getFoo() ); // alerts "bop" because we overrode the definition of getFoo
alert( b.supers().getFoo() ); // alerts "bar" because it accesses the supers' method
In this picture, we can see what occurs when we have simply a super object to contain super methods. This would result from the basic extend of Object, in the constructor A. We can see the relationships between the context object, this, which has a super object and some method some method foo, which has access to the context of A, which contains the context object as a variable:
Next we can see the result of an extend of A with a super object to retain the methods for use later:
In this image you can see how we've added the original foo method to the super object, replaced the existing super object with the new one, and also created the new foo method with B.
Incase you're worried that this is smoke and mirrors, and that the super methods simply work on different variables, let's not override anything but instead have a setter method as well:
function C(){
var foo = "bar";
this.getFoo = function(){ return foo; }
this.setFoo = function( newFoo ){ foo = newFoo; }
}
function D(){
this.extend(C);
}
var d = new D;
alert( d.getFoo() ); // alerts "bar", as expected
alert( d.supers().getFoo() ); // alerts "bar" as expected
d.setFoo( "baz" );
alert( d.getFoo() ); // alerts baz, as expected
alert( d.supers().getFoo() ); // alerts baz
So we can see that the supers' methods and the objects methods both have access to the same scope variables, and why shouldn't they? After all, all we did was add a reference to the methods into the supers object. If we don't override the method, then both the object and it's supers object reference the same method, but if we do, we still retain the original method in the supers object.
Also worth noting is that I chose to define the constructor of the supers object as the constructor of the current object. I did this because it's often very convenient to create methods that create new versions of themselves. For instance, if we have a TwoDPoint class that has a method that does something like "new TwoDPoint", and then created a ThreeDPoint class that extends TwoDPoint, the inherited method will still produce a new TwoDPoint, even if it should be creating a new ThreeDPoint. This is avoidable by doing "new this.constructor", which will created a new instance of the same type of object that's executing it, regardless of how deep in an inheritance hierarchy.
Now, if we hadn't set the supers' class, we would have the small problem of not being able to use super methods that have that functionality. Why? Well when you call a super method, the object that's calling it, which also happens to be the context object, is not the object that you're sending the method call to, but rather the supers object. If there are any methods that do "new this.constructor", it will reference the supers object's constructor. If we had not defined it, it would default to Object, and had we defined it as anything other than the current object's constructor, like say Class (which seems reasonable), we wouldn't get a new version of the current object. Both are troublesome! But the fix is elegant and simple.
I hope you learned something from this! Next time I'll be going over class methods and inheritance with them. Have fun, and don't forget to experiment with JavaScript!
Ahh classical inheritance. The bane of any JavaScript developer's existence, at least if they're writing object-oriented code, anyway. Yahoo! lead JavaScript "guru", Douglas Crockford is a huge detractor of classical inheritance, perhaps because it's so poorly understood in JavaScript. Instead he supports his own "parasitic" inheritance. Well I'm here to tell you that classical inheritance isn't bad! It's not even good, it's great! Awesome, even!
I kid, to some extent. Parasitic inheritance isn't all that bad, really.In theory it's exactly like the classical inheritance that I propose, in some fashion anyway. So let's look at parasitic inheritance first. According to Douglas, we can construct an inheritable object oriented system by ignoring the context object entirely, and instead return our own object to return. A simple constructor using this paradigm looks like this:
function MyObject(){
var foo = "bar";
return {
getFoo: function(){
return foo;
}
}
}
var m = MyObject();
alert( m.getFoo() ); // alerts "bar", as expected.
When we call this, the scope variable is created, and a new object literal is returned, with all the fun getter and setter methods we could want to access the variables within that scope. And hey, no need for the "new" keyword either, since this function has a return value! We can take this concept one further to create inheritance:
function Super(){
var foo = 5;
return {
getFoo: function(){
return foo;
}
}
}
function Sub(){
var that = Super();
var bar = 10;
that.getBar = function(){
return bar;
}
return that;
}
var o = Sub();
alert( o.getFoo() ); // alerts 5 as expected
alert( o.getBar() ); // alerts 10, also as expected
So what's wrong with this? Well, nothing really. In fact, it work's exactly like what I advocate, only uglier. There is another add on that Crockford has for this: the "secret" variable, which will hold commonly accessible private variables:
function gizmo(id, secret) {
secret = secret || {};
secret.id = id;
return {
toString: function () {
return "gizmo " + secret.id;
};
};
}
function hoozit(id) {
var secret = {}, /*final*/
that = gizmo(id, secret);
that.test = function (testid) {
return testid === secret.id;
};
return that;
}
var h = hoosit("foo");
alert( h.toString() ); // alerts "gizmo foo"
alert( h.test("foo") ); // alerts true
Now I must say, this way of doing things is very useful. You have shared private variables and you have inheritance. The only problem is that it looks ugly. Now let's explore an alternative. Instead of discarding the context object, let's take full advantage of it. So my first idea, based on Douglas's code there, looks something like this:
function gizmo(id) {
this.id = id;
var foo = "bar";
this.toString = function(){
return "gizmo " + secret.id;
}
}
function hoozit(id) {
gizmo.call( this, id );
this.test = function(testid){
return testid === this.id;
}
this.getFoo = function(){
return foo;
}
}
var h = new hoozit("bar");
alert( h.toString() ); // alerts "gizmo bar", as expected
alert( h.test("bar") ); // alerts true, as expected
alert( h.getFoo() ); // breaks the script, because foo is in a different scope
This works exactly like parasitic inheritance, but it uses the context object (and thus the "new" keyword).
Let's look real quick at why this works as we want it to.
Functions, in JavaScript, are objects too, and have methods associated with them. One of these methods is called "call". Call does something very simple: it calls a the function. Call can take a number of arguments, too, the first of which is the object that you want to use a the context object. That's right, you can apply a function to an object, as if that object were the context object of the function. The arguments after that are simply the arguments you normally would include in the function.
The way this works becomes clearer with visuals. In the case of two separate function calls, things look like this:
When we use call(), however, things look like this:
The context object is the same for, has the methods of, and thus has access to the scopes of both constructor functions. However I'm sure you'll notice that it lacks the shared private variables. with this paradigm, methods created in one constructor cannot directly access the private variables of any scope but it's own. I see no problem with this, assuming you have getter and setter methods for the variables you wish to access, but if you want absolutely must have mutually accessible private variables, no problem:
function gizmo(id, secret) {
var secret = secret || {};
secret.id = id;
secret.foo = "bar";
this.toString = function(){
return "gizmo " + secret.id;
}
}
function hoozit(id) {
var secret = {}; // final
gizmo.call( this, id, secret );
this.test = function(testid){
return testid === this.id;
}
this.getFoo = function(){
return secret.foo;
}
}
var h = new hoozit("bar");
alert( h.toString() ); // alerts "gizmo bar", as expected
alert( h.test("bar") ); // alerts true, as expected
alert( h.getFoo() ); // alerts "bar", as expected
This slight modification, dependent upon the "apply" method, lets you have everything of Douglas's parasitic inheritance, but in a smaller, cleaner form factor.
I personally dislike the use of "secret"; I think that if you're going to completely change the accessibility of a variable, you should redefine it, as it's theoretically no longer the same variable at all. However if you want and need something like "secret", then by all means, use it. In my experience, variable redefinition is very rare, despite the extraordinary scale of the Jade project.
I would also advocate against it because using the "secret" variable introduces the possibility that programmers could insert things into new objects that aren't inherited from others. Now, if a programmer wants to write a bad script, thats fine, but the less opportunity there is to mess things up, the better, especially if it's at less effort, not more.
Hope you enjoyed this. Next time I'll take a look at some more stuff dealing with inheritance. Keep exploring JavaScript; explore what it can do!
Previously I discussed scope in JavaScript, and how these scopes can remain accessible well after their original functions finished executing. Now I'm going to talk about something a little more mysterious: The context object.
What exactly is the context object? Well it's quite simple, really. JavaScript defines a variable, "this", called the context object. This variable cannot be redefined by you, at least not in any traditional fashion, and trying to do so will break your script, but other than that it's completely accessible like any other object, and like other scope variables, exists only within it's particular scope.
The context object is by default the window, and so any function that you create will consider the the window it's context object. For instance:
function testContext(){
alert(this);
}
testContext(); // alerts [object Window], which is the representation of the window object
However, the use of the "new" keyword will call a function with a new context object, so with a slight modification:
function testContext(){
alert(this);
}
new testContext(); // alert [object Object]
The function now executes with a completely new context object. The new keyword will also extract and return the context object when the function completes. The use of the new keyword also eliminates the need for the parentheses when calling zero-argument functions.
var m = new testContext(); // m is now set to the new context object
var n = new testContext; // same result, n set to another new context object
We can attach variables to the context object like any other object as well, when we call the function that creates it:
function MyObject(){
this.foo = "bar";
}
var o = new MyObject;
alert(o.foo); // alerts "bar"
Now recall that if a function is created by another function, it has access to the scope of the function that creates it. This is means we can attach these functions to the context object, and they will behave just like foo in the previous example, when used with the "new" keyword:
function MyObject(){
var foo = "bar";
this.getFoo = function(){
return foo;
}
}
var o = new MyObject;
alert( o.getFoo() ); // still alerts foo, because getFoo was created in, and has access to the context of, the MyObject function
It should be clear now that the use of the context object, along with the "new" keyword, makes it possible to create objects that have what are effectively private variables. The object itself doesn't contain the variables, they exist in the scope of the function that created them, but since that scope is unique for each function call, it pairs up with it's context object in a way that works well for private variables.
I hope you found this useful! Next time I'll go over some more OO JS and address another crucial aspect of any object oriented programming language: Inheritance!
I figured I would share some of my recent explorations into JavaScript's ability to function as an object-oriented programming language with everyone (all none of you that read my blog ;)). I'm going to try to do this in a tutorial like manner, and I'm going to expect that you know something about JavaScript already.
First, and absolutely most important to understand, is JavaScript's scoping rules. Scope is absolutely important in making JavaScript work like a real object-oriented language.
In JavaScript, the creation of variables occurs within a specific scope. The scope is, oddly, enforced by the use of the "var" keyword. When this keyword is not present, a variable is created in the global scope – it's visible everywhere and accessibly by everything. When the "var" keyword is present, the variable exists only within the scope that it's created.
Scopes have a number of different forms. As I mentioned already, one of these is the global scope, which is the script as a whole. Another scopes exist within functions:
var bar = 5;
function doSomething(){
var bar = 10; // a different bar
alert(bar);
}
doSomething(); // alerts 10, from the definition
alert(bar); // original bar, alerts 5
Compare that with this:
var bar = 5;
function doSomething(){
bar = 10; // same bar, redefined
alert(bar);
}
doSomething(); // alerts 10 still
alert(bar); // alerts 10 again due to redefinition of bar
Another important feature of JavaScript, and indirectly of scopes, is that there seems to be some sort of garbage collection that will remove variables and their content when they're no longer accessible by anything (that is, when they are completely isolated from the script and can't affect anything anymore).
This has a very important affect for us. When we talk about scoped variables, in most contexts, when we call a function or create a loop, once we've finished using it, we don't use the variables from inside ever again. And of course we normally couldn't, even if we wanted to, because they exist only within the scope of the loop or function. So the scope is discarded.
However, because scopes, or the variables at least, are discarded only when they're inaccessible, we can prevent this from happening by keeping the variables accessible. For instance, if we have a function that creates functions, if the one that's created has references to variables within the scope of the function that created it, then those variables will still be accessible.
Take for instance this function:
function foo(){
var foo = "bar";
return function(){
alert(foo);
}
}
This function has a variable within it's scope: foo. This variable is accessible to the function that is returned. So continuing from there:
var baz = foo(); // assigns baz to the function returned by foo(). baz is now a function.
baz(); // alerts "bar", since this is what foo was defined as before
From this we can see that even while the function foo() has finished running, it's scope is still accessible to the function baz(). This is because foo() creates a function that can access it's scope, and then returns that function. The scope access remains intact.
I hope this made sense and is enlightening. This simple feature of JavaScript opens a whole lot of doors that otherwise would be closed, and next time I'll go over some of those. The key to good JavaScript is a full understanding of the language, and the best way to get that is by experimenting. Explore!
So JavaScript's this Object Oriented language without classes, as such. Well, in a way it does have classes, because you can use constructor functions that end up behaving like class definitions:
function MyClass(){var foo = 5; // private variablethis.bar = -1; // public variable}
Which is very nice and efficient and I think much better than working with prototypes, which end up creating only public variables, and no unique objects for properties:
function MyClass(){ ... }MyClass.prototype.foo = 5;
MyClass.prototype.bar = {}; // all instances reference this same object! bad bad bad
But how do you inherit the private variables? Well it turns out that it's very easy. JavaScript provides you with the ability to call one function in the context of a specific object, so that the "this" keyword refers to that object. You do it with the "apply()" method of functions. So you can have two constructors, one which calls apply on the other, and you get inherited private variables:
function MyClass(){var foo = 5;this.getFoo = function(){ return foo; }}function OtherClass(){MyClass.apply(this);}var o = new OtherClass;alert( o.getFoo() ); // alerts 5
Now I have to go back and recode everything to take advantage of this. My task:
Turn this:
...this.property = someValue;...
into this:
...var property = someValue;...this.property = function(){ return property; }...
A few thousand lines of code, that's all... It will be fun, I'm sure...