在一个表达式中返回一个新对象并修改其属性

时间:2015-09-24 16:59:36

标签: javascript functional-programming

我发现自己想要从功能中返回180度色调旋转的颜色。我的项目使用的是D3,这就是我用来执行此操作的库。不幸的是,D3并没有提供旋转色调的功能。

这个问题并非针对D3,我只是以它为例。

所以我必须做这样的事情:

var c = d3.hsl(colorString);
c.h += 180;
return c;

简明扼要,但它有三个表达方式。不会刮伤我的书呆子痒。我希望我能做的是:

return d3.hsl(colorString).h += 180

但显然只返回h的值,而不是整个对象。

这是我不得不诉诸的荒谬建筑,使用一些Underscore.js:

return  _.create(Object.getPrototypeOf(d3.hsl()),
        _.mapObject(d3.hsl(colorString), function(val, key) {
            return key === "h" ? val + 180 : val;
        }));

请参阅,我不能只返回mapObject()的结果,因为它仍然需要使用d3.hsl()返回的原型,这就是为什么我需要将它包装在create()中1}}。

所以这很有效。这有点荒谬。

我有什么方法可以在一行中做某事,比如......

return d3.hsl(colorString).with180AddedToH();

3 个答案:

答案 0 :(得分:0)

你可以返回一个函数,为什么不呢:

function with180AddedToH(obj) {
    obj.h += 180;
    return obj;
}

然后:

return with180AddedToH(d3.hsl(colorString))

或者这只会发生一次?这太过分了?

答案 1 :(得分:0)

你可以在这里制作另一个答案的更通用版本,如:

console.log(mutate(o, {h: o.h + 180, j: "abc"}));

function mutate(o, m){
    for(p in m){
        if (p in o){
            o[p] = m[p];
        }
    }
    return o;
}

但你仍然需要将你的变量绑定到另一行,以便引用它两次。您可以更改此函数以接受mutator函数的对象,如:

console.log(mutate(d3.hsl(colorString), {h: function(x){return x + 180}}));

function mutate(o, m){
    for(p in m){
        if (p in o){
            o[p] = m[p](o[p]);
        }
    }
    return o;
}

它在属性名称上匹配,并将该函数应用于属性然后设置它。然后它返回对象,以便最终得到

return mutate(d3.hsl(colorString), {h: function(x){return x + 180});

对于你正在尝试做的事情似乎仍然有点沉重,但在适当的情况下可能会有用。虽然在ES6中你可以逃脱:

return mutate(d3.hsl(colorString), {h: x => x + 180});

答案 2 :(得分:0)

您可以使用Object.assign。它已在ES2015中生成,但如果您需要支持其他版本的JavaScript,则会提供填充。

function rotateHue(colorObj, degrees) {
  return Object.assign(colorObj, {h: colorObj.h + degrees});
}

rotateHue(d3.hsl(colorString));

这与mafafu提供的mutate函数非常相似,而是使用JavaScript本机。