简体   繁体   English

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

[英]Returning a new object, and modifying its property, in one expression

I found myself wanting to return a 180 degree hue-rotated color from a function. 我发现自己想从函数中返回180度色相旋转的颜色。 My project's using D3, so that's the library I'm using to do this. 我的项目正在使用D3,所以这就是我用来执行此操作的库。 Unfortunately, D3 doesn't come with a function to rotate the hue. 不幸的是,D3没有附带旋转色相的功能。

This question is not specific to D3, I'm just using it as an example. 这个问题不是D3特有的,我仅以它为例。

So I had to do something like this: 所以我必须做这样的事情:

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

Concise, but it's three expressions. 简洁,但这是三个表达。 Doesn't scratch my nerd itch. 不会划伤我的书呆子痒。 What I wish I could do is: 我希望我能做的是:

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

but obviously that just returns the value of h , not the entire object. 但是很明显,它只是返回h的值,而不是整个对象。

Here is the ridiculous construction I had to resort to, using some Underscore.js: 这是我不得不使用一些Underscore.js进行的荒谬构造:

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

See, I can't just return the result of mapObject() because it still needs to use the prototype of what d3.hsl() returns, which is why I needed to wrap that in a create() . 瞧,我不能仅仅返回mapObject()的结果,因为它仍然需要使用d3.hsl()返回的原型,这就是为什么我需要将其包装在create()

So this works. 所以这可行。 It's just kind of ridiculous. 这简直太荒谬了。

Is there any way that I could do something in one line, such as... 有什么办法可以使我一行完成某件事,例如...

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

you can return a function so why not: 您可以返回一个函数,为什么不这样:

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

and then: 接着:

return with180AddedToH(d3.hsl(colorString))

or is this only going to occur once? 还是只会发生一次? and this is too much? 这太多了吗?

You could make a more generic version of the other answer here like: 您可以在此处对其他答案做出更通用的版本,例如:

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;
}

but you still have to bind your variable on another line in order to reference it twice. 但是您仍然必须将变量绑定在另一行上才能两次引用它。 You could alter this function to accept an object of mutator functions like: 您可以更改此函数以接受诸如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;
}

Where it matches on property name and applies that function to the property and then sets it. 它在属性名称上匹配的位置,然后将该函数应用于属性,然后对其进行设置。 It then returns the object so you could end up with 然后,它返回对象,因此您可能最终得到

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

which still seems a little heavy for what you're trying to do, but in the right circumstances might be useful. 对于您要执行的操作,这似乎还有些繁重,但在适当的情况下可能会有用。 Although in ES6 you could get away with: 尽管在ES6中您可以摆脱:

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

You can use Object.assign . 您可以使用Object.assign It's native in ES2015 but there's a polyfill provided if you need to support other versions of JavaScript. 它是ES2015的本机,但是如果您需要支持其他版本的JavaScript,则可以使用polyfill。

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

rotateHue(d3.hsl(colorString));

This is quite similar to the mutate function provided by mafafu, but instead uses a JavaScript native. 这与mafafu提供的mutate函数非常相似,但使用的是JavaScript本机。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM