Home > Enterprise >  Optional values from object in javascript
Optional values from object in javascript

Time:01-29

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. This guy uses the operator ||, but it just do not work for me.

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

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

CodePudding user response:

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

CodePudding user response:

The error is occurring because the optional chaining operator (?.) is not supported in the version of JavaScript that the online compiler is using. The optional chaining operator is a relatively new feature in JavaScript, and is supported in version 12.0 and later of the language.

You can use a different approach to achieve the same result. One way is to use the in operator to check if the property exists in the object, and then use the || operator to provide a default value if the property does not exist.

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

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

You can also use Object.prototype.hasOwnProperty() method to check if the property exist in the object.

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

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

In the above example, the console.log statement is creating a new object that has properties "a", "b", and "c". The values of these properties are determined by checking if the corresponding property exists in the original object, and using the value from that property if it does exist, or using the default value (2, 4, or 6) if it does not exist.

CodePudding user response:

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

CodePudding user response:

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

CodePudding user response:

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.

CodePudding user response:

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,
}
  • Related