我正在阅读Michael Fogus的书 Functional JavaScript ,本书中的一个例子不起作用。这是代码:
function existy(x) {
return x != null;
};
function truthy(x) {
return (x !== false) && existy(x);
};
function cat() {
var head = _.first(arguments);
if (existy(head))
return head.concat.apply(head, _.rest(arguments));
else
return [];
};
function construct(head, tail) {
return cat([head], _.toArray(tail));
};
function rename(obj, newNames) {
return _.reduce(newNames, function(o, nu, old) {
console.log("o: " + o);
console.log("nu: " + nu);
console.log("old: " + old);
if (_.has(obj, old)) {
o[nu] = obj[old];
return o;
}
else
return o;
},
_.omit.apply(null, construct(old, _.keys(newNames))));
};
rename({a: 1, b: 2}, {'a': 'AAA'});
// => {AAA: 1, b: 2}
除rename()外,所有功能都能正常工作。本质上,它的目标是获取一个对象并返回具有使用newName对象更新的属性名称的对象。我并不完全理解它,但是reduce方法看起来并没有正确的参数。这是我调用rename()时得到的错误:
ReferenceError: old is not defined
任何有助于理解它不起作用的帮助都将非常感谢!
答案 0 :(得分:3)
function rename(obj, newNames) {
return _.reduce(newNames, function(o, nu, old) {
console.log("o: " + o);
console.log("nu: " + nu);
console.log("old: " + old);
if (_.has(obj, old)) {
o[nu] = obj[old];
return o;
}
else
return o;
},
_.omit.apply(null, construct(old, _.keys(newNames))));
}
调用时,执行
_.reduce(newNames, function(o, nu, old) {
console.log("o: " + o);
console.log("nu: " + nu);
console.log("old: " + old);
if (_.has(obj, old)) {
o[nu] = obj[old];
return o;
}
else
return o;
},
_.omit.apply(null, construct(old, _.keys(newNames))));
调用
_.omit.apply(null, construct(old, _.keys(newNames)))
和old
仅存在于_.reduce
的回调中。如果它是第一个对象,您可以使用newNames[0]
。
但我不相信一本在函数定义之后添加分号的书......
就个人而言,如果我要实现“功能性”,它看起来像这样:
function objectMap(obj, func) {
var result = {};
for (var x in obj) {
if (obj.hasOwnProperty(x)) {
var r = func(x, obj[x]);
result[r[0]] = r[1];
}
}
return result;
}
function rename(obj, newNames) {
return objectMap(obj, function(k, v) {
return [newNames[k] || k, v];
});
}
答案 1 :(得分:1)
Per @minitech,问题是“旧”只存在于_.reduce
回调中,因此当它在_.omit
函数中调用时,它超出了'old'的范围。事实证明,有一个简单的解决方案。如果你将'old'改为'obj'(这可能是作者的意图),该函数似乎正常工作并保留其功能性:
function rename(obj, newNames) {
return _.reduce(newNames, function(o, nu, old) {
if (_.has(obj, old)) {
o[nu] = obj[old];
return o;
}
else
return o;
},
_.omit.apply(null, construct(obj, _.keys(newNames))));
};
rename({a: 1, b: 2}, {'a': 'AAA'});
// => {AAA: 1, b: 2} -> success!