1

我正在阅读 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

任何帮助理解为什么它不起作用将不胜感激!

4

2 回答 2

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].

但我不会相信在函数定义后加分号的书……</p>


就个人而言,如果我要实现“功能性”,它看起来像这样:

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];
    });
}
于 2013-10-28T05:08:48.393 回答
1

根据@minitech,问题在于“旧”仅存在于_.reduce回调中,因此在_.omit函数中调用它时,它超出了“旧”的范围。事实证明,有一个简单的解决方法。如果您将 '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!
于 2013-10-28T18:37:31.757 回答