Books & Tools Techniques

Comprehensive coverage of Ruby 1.8 and 1.9

"The New Most Important Ruby Book"
Peter Cooper,
rubyinside.com

Completely updated for Ajax and Web 2.0

"A must-have reference"
Brendan Eich,
creator of JavaScript

Jude

Jude is my Java documentation browser. It combines Sun's definitive javadocs with the easy-to-use format of Java in a Nutshell, and tops it off with easy keyboard-based navigation and full-text searching.

Jude is available for free evaluation.

See the user's guide for more info

Java in a Nutshell

The 5th edition is now out, with complete coverage of Java 5.0!

It includes a fast-paced tutorial on the language, and a compact quick-reference for the core Java API.

Java Examples in a Nutshell

The 3rd edition, updated for Java 1.4

This edition has all-new coverage of the NIO and JavaSound APIs, completely rewritten Servlets and XML chapters, and coverage of new Java 1.4 features (assertions, logging, preferences, SSL, etc.) added througout. A great book for those who like to learn by example. 193 working examples: 21,900 lines of carefully commented code to learn from.

Java 1.5 Tiger: A Developer's Notebook

Amazon incorrectly credits me as the main author on this book. I'm actually the second author: really more of a consultant. This is a good book about all the language changes in the latest version of Java.

Effective Java

I didn't write this excellent book, but I wish I had.

Author Josh Bloch is probably best known for the collections classes in the java.util package. His experience and wisdom are apparent in this book. I learned from it and recommend it highly.

October 27, 2006

Constructor and Method Chaining Convention for JavaScript

In the 5th edition of my book, I propose a convention for constructor chaining:

  • When you define a class B as a subclass of A, set B.prototype.superclass=A
  • Then, in the constructor B(), you can chain to the superclass constructor with the natural syntax this.superclass()

Reader Bruce Wallace has just pointed out a serious flaw in this approach: you can only use it once. If you use this trick twice in the same inheritance hierarchy, you end up with infinite recursion. (If you don't see why, you can try to work out an example that includes C as a subclass of B. Or just forget it, since I think I have a better approach below.)

I'm feeling pretty embarassed to have suggested this defective method of chaining, and to have committed my suggestion to print! However, I hope to make up for it by proposing a better alternative. Here is my new convention:

  • First, define the following function:
    function super(o, args) {
        if (args.callee.superclass)
    	return args.callee.superclass.apply(o, args);
    }
    
  • For each constructor B that subclasses A, set B.superclass=A;
  • Do the same thing if a method of B overrides a method of A. For example:
    B.prototype.toString.superclass = A.prototype.toString;
    
  • In the B() constructor, chain to your superclass constructor like this:
    super(this, arguments)
    
  • And in a method like B.toString(), chain to A.toString() with exactly the same syntax.

This works because arguments.callee is the function that is currently running. Note that this chaining convention passes all the arguments of the subclass constructor or method to the superclass constructor or method, even if some of them are unused. So it won't work if a subclass constructor expects its arguments in a different order than the superclass constructor.

Note that the work of setting the superclass property on constructors and methods can be done by a suitable class definition utility method (such as example 9-10) in my book. This means that when writing your constructors and methods, you don't have to worry about linking the chain together; you can just call the super() method whenever you want to.

Anyone see any flaws in this approach? Comments? Suggestions? There is a simple test case defining a class hierarchy C extends B extends A below, but I haven't tried to test this extensively yet, and I''ve only run it in Firefox. Firefox is letting me use the function name "super" even though that is one of the identifiers that is unused but nominally reserved by ECMAScript v3. I choose super because Java uses that, but "chain" would probably be a safer choice.

Here is my test code:

// Magic constructor and method chaining function
function super(o, args) {
    if (args.callee.superclass)
	return args.callee.superclass.apply(o, args);
}

// Class A
function A(a) { this.a = a; }
A.prototype.toString = function() { return this.a + "" };

// Subclass B
function B(a, b) {
    super(this, arguments);
    this.b = b;
};
B.superclass = A;
B.prototype = new A();
B.prototype.toString = function() {
    return super(this, arguments) + this.b;
};
B.prototype.toString.superclass = A.prototype.toString;

// Sub-subclass C
function C(a,b,c) {
    super(this, arguments);
    this.c = c;
}
C.superclass = B;
C.prototype = new B();
C.prototype.toString = function() {
    return super(this, arguments) + this.c;
}
C.prototype.toString.superclass = B.prototype.toString;

// Create an instance of C and call toString() should display "123"
var c = new C(1, 2, 3)
alert(c.toString());

October 23, 2006

IE, event objects, and attachEvent()

In the 5th edition of my JavaScript book, I wrote:

Although the IE event model provides event details in an Event object, it never passes Event objects as arguments to event handlers.

I don't know how I know this: it is just one of those things I've always known about IE. But a reader (Tom Stambaugh of zeetix.com) just emailed me with a trivially simple counter example. It turns out that if you use attachEvent() (at least in IE 6) then the event handler you specify is passed an event object as an argument.

I don't think I'm the only one who believed that handlers registered with attachEvent() don't get passed an event object. For example, the documentation on attachEvent() at about.com says:

Also unlike the standard DOM method, the event is not passed to the function as a parameter. Instead IE supplies a standard window.event object to hold the details relating to the latest event.

And the documentation for the YUI event library advertises, as a feature of the library, that:

The first parameter your callback receives when the event fires is always the actual event object. There is no need to look at window.event.

The documentation at MSDN is not helpful. It does not say whether or not an event object is passed and the examples it lists don't use any event details.

Does anyone out there know what is up here? Has attachEvent() always caused an event object to be passed to the handler, or is this something that changed in IE 5.5 or IE 6? I don't have an old version of IE I can test this against. I recognize that with the release of IE 7 we may all have better things to do than fire up IE 5, but I'd like to get to the bottom of this!

Update: Thanks to the commenters who have pointed out the interesting fact that the event object passed to a handler is not the same object (not == to) window.event. I've written a trivial test that demonstrates that 1) an object is passed to a handler registered with attachEvent(), 2) that this object is not == to window.event, and that 3) the properties of this object are the same as the properties of window.event (except that they both have a property that refers to different empty arrays).

Note that the test linked to above only runs in IE, so don't bother trying it out in other browsers. If someone has an old version of IE around and is willing to test it, I'd love to hear what you find out. IE 5, IE 5.5, IE 5 on a Mac? Surely this fails on some old version of IE! Otherwise I, and many others, deluded ourselves into thinking that attachEvent was broken in a way that it was not broken.

This winning entry into ppk's addEvent() recoding contest" is another example where the assumption is made that attachEvent() does does not [oops. typo in original post] cause the handler to be invoked with an event object.

Update 2: In comments, Alistair Potts presents test results that indicate that attachEvent has always passed a copy of the window.event object to event handlers. His test code is at: http://www.partyark.co.uk/html/ieeventtest.htm

The next test to undertake will be to determine if setting cancelBubble and returnValue on the event object passed to the handler works the same way as setting them on the global window.event object.

October 07, 2006

Nifty DOM output stream class

I was porting some JavaScript code that used the TrimPath template library. The templating system was too much for my needs, so I came up with the simple little class below. It simulates a Java-style output stream. Pass the id of a DOM element to the constructor to get started. Call the clear() method first, if necessary. Then call the write() method as many times as needed. Finally, always remember to call flush() to force your output to appear.

// A little class for outputting HTML into a DOM element
function DOMStream(id) {
    this.elt = document.getElementById(id);
    this.buffer = [];
}
DOMStream.prototype.clear = function() { this.elt.innerHTML = ""; };
DOMStream.prototype.write = function() {
    for(var i = 0; i < arguments.length; i++) this.buffer.push(arguments[i]);
};
DOMStream.prototype.flush = function() {
    this.elt.innerHTML += this.buffer.join("");
    this.buffer.length = 0;
};

If it is not obvious, an important point of this class it to avoid inefficient repeated string concatenation. This is why it uses an array as a buffer, and why the write() method accepts multiple arguments--so you don't have to concatenate them yourself.

Here's a sample usage:

var out = new DOMStream("placeholder");
out.write('<h2>', section_title, '</h2>');
outputTable(out, data);  // Function defined elsewhere
out.flush();

With this class defined, I ported the trimpath template to equivalent JavaScript functions, and ended up with a modest reduction in the number of lines of code (not counting the substantial reduction in lines of code I got by no longer using the templating library.)

October 04, 2006

Notable New JavaScript Books

The 5th edition of my book was not the only notable JavaScript book released this summer. I'd like to draw your attention to these two as well:

The authors of these two books, Christian Heilmann and Peter-Paul Koch, were kind enough to serve as technical reviewers on my book, and were also kind enough to send me copies of their own books.

I cannot actually review their books, however, since I have not had the time to read them. Nevertheless, the author's reputations speak well for the books. Both Christian and Peter-Paul are active web developers, members of the DOM Scripting Task Force (of the Web Standards Project) and advocates for unobtrusive scripting, accessibility, and other modern scripting practices.

Neither of these books aims to be "definitive" in the way mine does, but both are written by authors who have a lot of valuable experience with todays best practices. Since I haven't read the books myself, I can't tell you whether they share that experience effectively in these books. But I hold the authors in high esteem and want others to be aware of their work.

Advertising
About
Store
Search
Google
Web this site
Archives
Syndicate

Powered by
Movable Type