我正在为MongoDB开发一些Map / Reduce查询,并尝试执行以下操作(简而言之)。
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
*/
应该注意的是,我将其写为Node.js应用程序,但我认为大多数相同的主体都适用于任何JavaScript。
问题是我不认为我可以在不创建对象的情况下更改它,ala mTmp = new m();
,但我不能,因为emit()
(以及其他所有内容)未定义。
我尝试使用m.prototype.convert = function
,但这不起作用。 m.toString()
的值不会改变。
答案 0 :(得分:1)
我认为您尝试加入m
(地图函数)的行为会有所不同,具体取决于是否设置了tuned
。是吗?
不幸的是,由于map和reduce函数都只是作为函数体的字符串传递给MongoDB,因此它们无法访问任何外部代码或数据 - 因此您在函数上设置的任何属性都会赢得'当它被执行时就在那里。
如果我理解正确,我认为这是你最好的三个选择:
为每种情况定义不同版本的m
。
将m
汇总为一个字符串,根据tuned
的值,插入正确的代码块。
让m
根据变量决定行为方式,如下所示:
m = function()
{
var result;
if (tuned) {
result = this.age;
} else {
result = this.age + 1;
}
emit(convert(this.age), this.doesWearGlasses);
}
...当你致电tuned
时,给mapReduce
变量在MongoDB中第二次生命:
collection.mapReduce(m, r, { scope: { tuned: tuned } });
(FWIW,如果不同之处,实际上就是这么简单,你可以这样写m
代替:)
m = function()
{
emit(convert(tuned ? this.age : this.age + 1), this.doesWearGlasses);
}
...如果你的意思不同,请告诉我。
答案 1 :(得分:0)
由于您在定义prototype
函数后调用构造函数,this.convert
将覆盖已定义的原型函数。
您可以覆盖整个m
构造函数:
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);
它应该可以工作,但我不知道它可能会对你的实际脚本产生什么影响。
请注意,它使用self-invocation模式,这会创建一个闭包。
我添加了测试代码,证明这可以在OP中给出约束。