18 comments

[ 2.7 ms ] story [ 45.4 ms ] thread
I implemented something like this for my last project, but I think you can make JS class creation far more ruby-like (and flexible, for that matter), by not passing an explicit hash to your class creation function, but instead building the class in a callback:

  // code start
  var Event = Class.define(function()
  {
    this.speak = function()
    {
       console.log("HI");
    }

    // since you can just write code in here
    // metaprogramming is easy:
    ["attack", "defend"].each(function(name) {
    this[name] = function() {console.log(name);}
    }.bind(this));

    // or build reusable metaprogramming facilities
    // and use them here
    this.$setters(["x", "y", "z"]);
    this.$memoize("expensiveFunc", function() {
         // blah
    });
    this.$inherited = function(derivedClass) { ... }
});

Basically, the class define method would create a special 'class-creation' object, and would invoke the user provided function with the class creation object as the this pointer. After the callback finished, I would use the class-creation object to build the actual class.

Being actual able to write code inside your class definition is a much more flexible way to define your objects - and it's also how Ruby does it.

Looks nice, but I'm not sure why JavaScript needs to be like Ruby.
Lack of classes is one reason to prefer JavaScript to Ruby. People always feel the need to add complexity where it isn't needed.
Yes, the lack of the class abstraction does add complexity to your code. That's why frameworks like this exist.
I was making the opposite assertion. How are classes simpler than prototypes? If you want to add behavior to the proto and the clone, you just add a method to the proto. If you want to add behavior to a class and its instances, you have to do a fair bit more.
Prototypes offer no contract, so it's up to the consumer to ensure that the object received is acceptable. Classes offer a contract, so if an object is an instance, it's guaranteed to work (Liskov, etc.).

Basically, the idea of OOP is information hiding and polymorphism, and prototype-based objects throw both of these concepts away. The result is more complicated code in general.

Ruby Classes don't provide a contract either. You can add and remove methods to your heart's desire.

information hiding is the principle of segregation of design decisions in a computer program that are most likely to change, thus protecting other parts of the program from extensive modification if the design decision is changed

http://en.wikipedia.org/wiki/Information_hiding

How are prototypes inferior to classes with respect to information hiding? They provide the ability to easily change the implementation while maintaining the interface.

How do prototypes inhibit polymorphism? All of the prototype languages that I know of (Javascript, Io, Self, Lua ...) make it easy to take advantage of polymorphism.

Less context switching when you're developing web applications that require a significant amount of Javascript code. Less context switching means you get to stay in flow and get more done.
There's a lot of useful functionality here that comes in handy. Just as a standard library, I think its useful.

Ruby Hashes and Enumerators have way more functionality than the stock js types.

Is it worth the 40k minimized for the full include? That I dunno.

What do those have to do with Ruby? Those things have nothing to do with Classes, Modules private / public ivars ...
Just like in Ruby, classes and modules are open for modification at any time, so you can add and change methods in existing classes.

Brings to mind the expression "A bug-for-bug port of the existing system."

Thanks, but no thanks. Prototypal inheritance is JavaScript's strength.
You can do prototype-style inheritance in ruby, but no one does it. In fact, most new languages that come out express no interest in this style. It makes me wonder why the Javascript people are so convinced that why they have is that good.
I don't know - I love PHP classes but I'd love to see PHP with prototype-style inheritance (if PHP had classes for strings, etc. in respect to basic variable types). I think the "everything is an object" route is great and coupling that with prototypes exemplifies that decision's greatness.

However, I really do think that JavaScript needs all of the great things ECMA 5 displays first and foremost (such as strict mode, getters/setters/enumerable/configurable/writable for property descriptors).

John Resig does an excellent job of summing up ECMA 5 pragmatically (it truly must be great to work on JavaScript stuff as a day job): http://ejohn.org/blog/ecmascript-5-objects-and-properties/

Coffeescript
Rocks. I love JS for what it is, even though I would equally love for CoffeeScript to be mainstream and natively supported across all browsers :)