views:

64

answers:

2

OK jQuery experts : So .. I'm coming from a Prototype background.

I do the following code all the time (or some similar variation):

MyObject.prototype.someFunction = function()
{
  var myArray = ["a","b","c"];
  myArray.each(function(arrayEntry)
    {
      this.printPart(arrayEntry);
    }, this);
}

MyObject.prototype.printPart = function(part)
{
  console.log(part);
}

I'm looking through the jQuery docs -- I don't see how to do this.

Is this possible?

In particular, I'm interested in:

  • Iterating through javascript arrays (objects would be nice too).
  • Maintaining scope. Notice the final "this" parameter to the each function.
+4  A: 
Pointy
+1 - Though you'll need to store what `this` is (unlike prototype), since `$.each()` creates a closure where `this` is the current element in it's callback.
Nick Craver
@Nick yes indeed, that's true. It's actually kind-of amazing how different are the programming styles imposed by those two libraries. That's why I generally moan and roll my eyes when somebody asks how hard it'll be to "convert a site from Prototype to jQuery" ...
Pointy
Hey also, if you really miss those Prototype things, check out the Underscore.js library - it's made to play nice with jQuery, and it adds some cool stuff.
Pointy
@Pointy: That's interesting. So in the jQuery world, is object scope not so important? I generally code my javascript to be very similar to Java, in that I'll have classes with methods. Calling those methods needs to maintain the correct "this" scope.
desau
@desau - Actually in this case you'd probably want `$.each(myArray, this.printPart);`, with `printPart` taking 2 params, `(index, part)`, this'll be the most concise way to get what you're after.
Nick Craver
@desau well object scope is pretty fluid in Javascript; in fact one way of thinking about it is that there's really no such thing as "object scope" in Javascript. There's no intrinsic binding between a function object and some other object that happened to be around when the function was defined. Trying to make Javascript act like Java is usually a way to make yourself frustrated and depressed. It's better to think of Javascript as a weird Lisp dialect, almost.
Pointy
@Pointy - I see your point. I guess instead of saying "like Java", I should have said "like an object-oriented language". But perhaps your comment about getting frustrated and depressed still applies. Perhaps trying to force a functional language into a OO paradigm is flawed from the start. Do the jQuery devs generally tend to not architect their client-side in an OO design?
desau
@desau if you look at it, there's not much about jQuery that you would call "object-oriented". There's no class definition mechanism, no inheritance system, really nothing that you'd expect from an OO framework. (Personally that suits me just fine!)
Pointy
+1  A: 

You don't necessarily have to do everything in jQuery. Just add a forEach method if it doesn't already exist, and use that instead. It was so good that ECMAScript 5th ed. adopted it as a standard (inspired by Prototype's each method), but not all browsers have it yet :). Here's an implementation by the spec that you can use until all browsers have it natively (taken from MDC):

Edit: Latest versions of Chrome, Safari, Firefox, and Opera already support this. No IE access, sorry.

if (!Array.prototype.forEach)
{
  Array.prototype.forEach = function(fun /*, thisp*/)
  {
    var len = this.length >>> 0;
    if (typeof fun != "function")
      throw new TypeError();

    var thisp = arguments[1];
    for (var i = 0; i < len; i++)
    {
      if (i in this)
        fun.call(thisp, this[i], i, this);
    }
  };
}

Then use your code as it is (change each to forEach):

var myArray = ["a","b","c"];

myArray.forEach(function(arrayEntry) {
    this.printPart(arrayEntry);
}, this);
Anurag