1

I'm in the process of writing a simple prototype in Node.js with some helper methods that I'll probably need in objects using that prototype. One method that I'd like to have is an implementation of jQuery's .each(). I've looked at jQuery's implementation in their development release, and tried to emulate it in my simplified version here.

// Loop through the object using a callback
BaseProto.prototype.each = function (cb, args) {
    var obj = this.get(),   // Get our object as a plain object
        prop;

    /** Code to make sure the the args passed are actually an array **/

    if (typeof cb === "function") {
        // For each property in our object
        for (prop in obj) {
            // Apply the callback to the object's property and pass
            // the index, the property, and whatever else as arguments
            if (cb.apply(obj[prop], [ prop, obj[prop] ].concat(args)) === false) {
                // Get out if the function returns false
                break;
            }
        }
    }

    // Reset our object with the new one
    return this.reset(obj);
};

The problem is that while the callback is definitely being fired, it doesn't have any effect on the object's property. No matter what I do inside the callback, the changes stay inside the callback's scope.

Here is an example of a simple callback that I've been testing with.

var BaseProtoTestObj = new BaseProto();

/** Set some properties to BaseProtoTestObj **/

function cb1 ( key, val ) {
    var prop;

    key = key.toString() + " Callbacked";
    val = val.toString() + " Callbacked";

    for (prop in this) {
        this[prop] = this[prop].toString() + " Callbacked";
    }
}

// Doesn't have any effect on BaseProtoTestObj
BaseProtoTestObj.each(cb1);

I can see that there is a lot more going on in jQuery's .each(), but from what I can gather it's for optimization and the ability to iterate over arrays as well as objects.

In the end, my question is simple. What is it that jQuery is doing to affect the properties, that I'm not in my .each()?


Edit

I suppose another question to ask would be if my logic is fundamentally wrong, and you can't modify an object's properties this way.

1
  • You can see jQuery's .each() here. It's at line 610. Commented Nov 10, 2011 at 19:38

1 Answer 1

2

You don't need a custom method:

for(var prop in object) {
   var value = object[prop];
   // do something with value and/or prop
}

Although if you really needed .each(), you could do something like this:

Object.prototype.each = function(cb) {
    for(var propName in this) {
        cb(propName, this[propName]);
    }
}

var foo = { prop: 'value', prop2: 'value2' };
foo.each(function(key,value) {
    // do something here
});    

Since you need to modify the actual values of the properties, try this:

Object.prototype.mutate = function(cb) {
    for(var propName in this) {
        this[propName] = cb(propName, this[propName]);
    }
}

var obj = {
    a: 'foo',
    b: 'bar',
    c: 'baz'
};

obj.mutate(function(propName, propValue) {
    return propName + '-' + propValue;
});

/*
obj will now be:

var obj = {
    a: 'a-foo',
    b: 'b-bar',
    c: 'c-baz'
};
*/
Sign up to request clarification or add additional context in comments.

4 Comments

For a lot of cases I probably won't need a custom method, but there are scenarios where applying a callback to each property of the object is preferable. Say that I'm saving something to a redis database for each property of my object. Since the redis library for Node.js is non-blocking, I would have to pass a callback for each save. Also creating functions in a loop isn't a good practice while using javascript, etc.
Your example is very similar to what I'm trying to do, but as you can see here it has the same problem as I'm describing in my question. You can't actually modify any of the properties from inside the callback.
I've been thinking about this in my spare time for a few days and the idea of returning what I wanted to set the property to did cross my mind. For whatever reason it feels like cheating though. For mutate() to be safe, I'd have to make sure the callback returned something or else all my properties would be undefined. I don't know if there are any better options though. I'm going to accept the answer, but I'd love it if I could read some more people's opinions. Thanks!
This is true. However, in my opinion that's the most flexible way, as there's really no way to indicate to the mutate function that you didn't change the value. Sometimes you want to change a value to false or null.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.