views:

58

answers:

1

I'm working on some Map / Reduce queries for MongoDB and am trying to do the following (in a nutshell).

m = function()
{
    this.convert = function(val)
    {
        return val+1;
    }

    emit(convert(this.age), this.doesWearGlasses);
}

r = function(k, v)
{
    count = 0;
    for(var i = 0; i < v.length; i++)
    {
        count += v[i];
    }
    return count;
}

if(tuned)
{
    m.convert = function(val)
    {
        return val;
    }
}

/**
* Continue to running the M/R query
*/

It should be noted that I'm writing this as a Node.js application, but I assume most of the same principals apply to any JavaScript.

The issue is I don't think I can change it without creating an object, ala mTmp = new m();, however I can't because emit() (and everything else) isn't defined.

I tried using m.prototype.convert = function, but this doesn't work. The value of m.toString() doesn't change.

A: 

Since you're calling the constructor after defining the prototype function, this.convert will overwrite the already-defined prototype function.

You could overwrite the entire m constructor:

m = function()
{
    this.convert = function(val)
    {
        return val+1;
    }
}

if(tuned) {
    m = (function(mOld) {
        return function()
        {
            mOld.apply(this, arguments);
            this.convert = function(val){ return val; }
        }
    })(m);
}

// Test code
function doStuff(obj) {
    alert(obj.toString());
}

var mObj = new m();
doStuff(mObj);

It should work, but I don't know what else it may affect in your actual script.

Note that it's using a self-invocation pattern, which creates a closure.

I've added test code that demonstrates that this works given the constraints in the OP.

palswim
Yeah, doesn't work.
Josh K
Then, we're going to need more code, because `alert((new m()).convert(4));` shows "4" (it would show "5" if it didn't work).
palswim
@palswim: I can't envoke m. I have create it and pass it, then `toString()` is called on it.
Josh K