简体   繁体   中英

Using ES6 spread operator on an object that is returned from a function

I am using a function to convert hex codes to rgb values, it's one I found on this site and all is working perfectly. The function takes in a string as an parameter, and returns an obj with r,g,b properties and their associated values.

I am then taking these values and printing them inside of a React functional component. I just wanted to tidy up the syntax and avoid:

rgbValue={'rgb=(' + hexToRgb('#000').r + ', ' + hexToRgb('#000').g + ', ' + hexToRgb('#000').b + ')'}

and replace it with something like:

rgbValue={ 'rgb=(' + ...hexToRgb('#000') + ')'}

Hoping that this would return the r,g,b values from the object and the end result would be:

rgbValue={'rgb=(0,0,0)'}

However, this is not working as expected. I do not know if this is a logic issue or a sytnax error. I am new to using the spread operator so I am not overly familiar with it but is there a way to achieve this using my current setup?

JS function being used to show what is returned:

function hexToRgb(hex) {
  // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
  var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
  hex = hex.replace(shorthandRegex, function(m, r, g, b) {
    return r + r + g + g + b + b;
  });
  var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
  // return rgb values as properties on an object
  return result ? {
    r: parseInt(result[1], 16),
    g: parseInt(result[2], 16),
    b: parseInt(result[3], 16)
  } : null;
}

I do not know if this is a logic issue or a sytnax error.

It's a syntax error. You can only use spread in the places where spread is defined (that's part of why it's notation/syntax, not an operator).

If you want to use the result of hexToRgb in string concatenation, you have a few choices:

  1. Have it return a string.

  2. Have it return an array and call .join(",") on that array; be sure the array is in r, g, b order.

     rgbValue={'rgb=(' + formatRgb(hexToRgb('#000')) + ')'}
  3. Have it return an object (always, not null sometimes) and use Object.values(hexToRgb('#000')).join(",") . Be sure the object is created in r, g, b order (yours is), and that this code only runs on a modern JavaScript engine. The order of object properties was only defined for Object.values very recently (a change that will be in ES2020); prior to that, although order existed for some operations, it wasn't required for Object.values and some others. But modern engines already implement the order that was defined, so as long as you don't have to transpile for IE11 or something like that...

     // See caveats in the text rgbValue={'rgb=(' + Object.values(hexToRgb('#000')).join(",") + ')'}
  4. Have a formatting function you pass the result into

    rgbValue={'rgb=(' + formatRgb(hexToRgb('#000')) + ')'}

I am not fully grasping this line

It's a syntax error. You can only use spread in the places where spread is defined (that's part of why it's notation/syntax, not an operator).

But I will look into it.

Fair enough, that's a very brief summary of a bit of a complex thing. Just FWIW:

... isn't an operator. An operator has operands (like a function's parameters) and a single result value (like a function's return value) and can be used just about anywhere an expression is expected. ... isn't an operator, and can't be, because it doesn't have a single result value. Instead, ... is defined as primary syntax with five meanings:

  1. Iterable spread : ... in an array literal or function argument list spreads out an iterable's values as discrete entries for the new array or discrete arguments for the function call.

 const source = [1, 2, 3, 4]; // In an array literal const dest = [...source, 5, 6]; console.log(dest); // [1, 2, 3, 4, 5, 6] function example1(a, b, c, d) { console.log(a, b, c, d); // 1 2 3 4 } // In a function argument list example1(...source);

  1. Rest parameter : ... before the final declared parameter in a function's parameter list marks the "rest parameter" that will receive all arguments provided from that point on as an array.

 function example2(a, b, ...rest) { console.log(`a = ${a}, b = ${b}, rest = ${JSON.stringify(rest)}`); } example2(1, 2, 3, 4); // a = 1, b = 2, c = [3,4]

  1. Property spread : ... in an object literal spreads out an object's own, enumerable properties a discrete propeties for the object being created.

 const source = {a: 1, b: 2, c: 3}; const dest = {...source, d: 4, e: 5}; console.log(dest); // {a: 1, b: 2, c: 3, d: 4, e: 5}

  1. Iterable rest (destructuring), the converse of iterable spread in an array literal: ... in an array destructuring pattern marks the target that will receive the "rest" of the iterable entries not consumed by other targets in the pattern (as an array).

 const source = [1, 2, 3, 4]; const [a, b, ...rest] = source; console.log(`a = ${a}, b = ${b}, rest = ${JSON.stringify(rest)}`); // a = 1, b = 2, rest = [3,4]

  1. Property rest (destructuring), the converse of property spread: ... in an object destructuring pattern marks the target that will receive the "rest" of the properties not consumed by other targets in the pattern (as an object).

 const source = {a: 1, b: 2, c: 3}; const {a, ...rest} = source; console.log(a); // 1 console.log(rest); // {b: 2, c: 3}

Outside of those, the meaning of ... is not defined and so it causes a syntax error.

Return Array instead

function hexToRgb(hex) {
  // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
  var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
  hex = hex.replace(shorthandRegex, function(m, r, g, b) {
    return r + r + g + g + b + b;
  });
  var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
  // return rgb values as properties on an object
  return result ? [
    parseInt(result[1], 16),
    parseInt(result[2], 16),
    parseInt(result[3], 16)
  ] : [];
}

rgbValue='rgb=(' + hexToRgb('#000').join(',') + ')';
// rgb=(0,0,0)

Firstly, this is an error because the spread operator only works for iterables (eg arrays), not objects (unless you're creating an object).

Secondly, if you were to work around this by converting the object values to an array first, eg ( ...Object.values(myHex) ), this would produce unexpected results since object entries are unordered. Ie, there is no guarantee that r would come before g .

IMO, you'r current code is sufficiently clear. But if you really want to use the spread operator, you can modify your hexToRgb to return an ordered array result.map(v => parseInt(v, 16))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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