2

My intent is to take the value from an object and pass it to other or use a default value if key doesn't exists. They use the operator ||, but it just do not work for me.

When I try to compile the snippet on code section in an online coding platform: https://www.programiz.com/javascript/online-compiler/, it throws throws an error:

Code:

const object = {
  "a": 1,
  "b": 2
};

console.log({
  "a": object?.a || 2,
  "b": object?.b || 4,
  "c": object?.c || 6
});

Error:

    "a": object?.a || 2,
                ^

SyntaxError: Unexpected token '.'
    at wrapSafe (internal/modules/cjs/loader.js:915:16)
    at Module._compile (internal/modules/cjs/loader.js:963:27)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
    at Module.load (internal/modules/cjs/loader.js:863:32)
    at Function.Module._load (internal/modules/cjs/loader.js:708:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:60:12)
    at internal/main/run_main_module.js:17:47
Michal Miky Jankovský
  • 3,089
  • 1
  • 35
  • 36
  • 5
    [Perhaps it is not supported on the compiler](https://caniuse.com/mdn-javascript_operators_optional_chaining) - the code works here, but for example the snippet 'linter' breaks the code if you 'tidy' it – mplungjan Jan 28 '23 at 13:45
  • 1
    this code is fine, the online interpreter you're using is outdated try running console.log(process.version) – Sombriks Jan 28 '23 at 13:48
  • You are fast. I can just say "thank you" – Bruno Peixoto Jan 28 '23 at 13:49
  • I’m wondering what the point of using this “online compiler” thing is. Why not use your browser console or Node.js directly? How did you even find this outdated platform? – Sebastian Simon Jan 28 '23 at 13:56
  • Leise, bitte. Well, a dear friend recommended it to me. Since I lived in Germany, such answer tone of yours does not surprise me anymore. – Bruno Peixoto Jan 28 '23 at 14:08
  • @BrunoPeixoto I have no idea why you’re making such an assumption about my “answer tone”. – Sebastian Simon Jan 28 '23 at 14:50

5 Answers5

2

It looks like whatever JavaScript engine that site is using doesn't support optional chaining (?.). But you don't need optional chaining in your example, object is never null or undefined — the properties on it may not exist, but object itself is never null or undefined. So just remove the ? ("a": object.a || 2,).

const object = {
    a: 1,
    b: 2,
};

console.log({
    a: object.a || 2,
    b: object.b || 4,
    c: object.c || 6,
});

That said, you might look for other sites (or run things locally). Optional chaining has been in the language for a couple of years now...

Another thing added at the same time as optional chaining is relevant here: ??, which is "nullish coalescing." It's probably what you really want for that code. While || will use the right-hand value if the left-hand value is any falsy value, ?? only uses the right-hand value if the left-hand value is null or undefined, specifically. Here's an example of the difference — note how I changed the value of a from 1 to 0, and note what gets logged after using each operator:

const object = {
    a: 0,
    b: 2,
};

console.log("Using ||:");
console.log({
    a: object.a || 2,
    b: object.b || 4,
    c: object.c || 6,
});

console.log("Using ??:");
console.log({
    a: object.a ?? 2,
    b: object.b ?? 4,
    c: object.c ?? 6,
});
.as-console-wrapper {
    max-height: 100% !important;
}

Notice how object.a || 2 used 2, but object.a ?? 2 used 0 (the value of object.a).

In cases where object might be null or undefined, you might want both optional chaining and nullish coalescing:

function example(object) {
    console.log(`Using ${JSON.stringify(object)}:`);
    console.log({
        a: object?.a ?? 2,
        b: object?.b ?? 4,
        c: object?.c ?? 6,
    });
}
example(null);
example({
    a: 0,
    b: 2,
});
.as-console-wrapper {
    max-height: 100% !important;
}
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
1

Might be because of wrong version of JS (?.) is relatively a new thing. You can go with either

object.a || 2

OR

object.hasOwnProperty('a') ? object.a : 2
vineet
  • 850
  • 7
  • 9
1

It is not the OR operator (||) but the optional chaining operator (?.) the one that produces the error.

The optional chaining operator ?. is new operator that has been introduced recently in the language and has been implemented in 2020 by most browsers. You are probably using an older version of the browser and it does not know about ?.

It means that if a is defined then the value of a?.b is a.b, otherwise it is undefined.

The expression a?.b is the same thing as a ? a.b : undefined. Alternatively it can be written as (a || {}).b.

Multiple operators in the same expression can be replaced by any of the above replacement by using parentheses. a?.b?.c can be written as:

  • (temp = a ? a.b : undefined) ? temp.c : undefined or
  • ((a || {}).b || {}).c

In this particular situation you don't even need the optional chaining operator because object is defined and object?.a is object.a.

Your code can be written as:

const object = {
  "a": 1,
  "b": 2
}

console.log({
  "a": object.a || 2,
  "b": object.b || 4,
  "c": object.c || 6
});
axiac
  • 68,258
  • 9
  • 99
  • 134
1

I am new to javascript. My intent is to take the value from an object and pass to other OR use a default value if key is inexistent

You may also want to look for nullish coalescing operator (??): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing

Using || for this kind of purpose may lead to unwanted consequences if the left-side operand is "falsy", but not undefined.

E.g.

const currentValue = 0;
const a = currentValue || 2;
console.log(a);
// => 2

As @mplungjan said,

Perhaps it is not supported on the compiler: https://caniuse.com/mdn-javascript_operators_optional_chaining

(Note: Caniuse only lists browser's JavaScript support. This is different from Node.js, which Programiz uses.)

I checked that Programiz uses Node.js v12.22.9, which does not support optional chaining (i.e., the ?. syntax). You can verify this by yourself:

// Online Javascript Editor for free
// Write, Edit and Run your Javascript code using JS Online Compiler
console.log(process);
node /tmp/Y4wzKlcLGW.js
process {
  version: 'v12.22.9',
  versions: {
    node: '12.22.9',
    v8: '7.8.279.23-node.56',
...

To have your environment supports optional chaining, you will need to use Node v14 or above (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining), OR set up a transpiler like Babel.

So, instead of running your JS files directly, you can first transpile them using Babe (which transforms your source files that may use the latest syntaxes, to syntaxes that your Node.js can understand), then run the transpiled files using Node.js as usual.

0

I recommend Object Destructuring here (this works for arrays and objects) --- it's one of the most useful bits of JS and I use it daily at work. destructure two objects inside curly braces and the later object's values will overwrite the earlier object's values.

here's a code snippet below -

const object = {
  a: 1,
  b: 2,
};

console.log({
  ...{
    a: 2,
    b: 4,
    c: 6,
  },
  ...object,
});

// output: {a: 1, b: 2, c: 6}

To make this more readable:

const object = {
  a: 1,
  b: 2,
};

const objectDefaults = {
  a: 2,
  b: 4,
  c: 6,
};

console.log({
  // 'object' will overwrite 'objectDefaults' here (only where the keys match)
  // otherwise the values from 'objectDefaults' are preserved
  ...objectDefaults,
  ...object,
});

// output: {a: 1, b: 2, c: 6}

But you have to put the objects in the right order. This would never work:

{
  ...object,
  ...objectDefaults,
}
Sean Mizen
  • 129
  • 8
  • 1
    Thanks, Mizen, your comment is a great way to solve somewhat the issue as well. I want to take the properties one-by-one and not update one object with the other. It is flexible in the sense that we can build partial objects. – Bruno Peixoto Jan 28 '23 at 14:12
  • I recommend you to rephrase "This would never work" to "This would never work because in this other way around you overwrite the desired values with default, which is undesirable." – Bruno Peixoto Jan 28 '23 at 14:24