2

I believe there's a mechanism for this in CoffeeScript (the ? token), but I'm wondering if there's a better way to do this kind of check in ES6:

if (item && item.integrations && item.integrations.slackData) ...

(besides writing a helper function, which is the immediately obvious solution)

EDIT: The goal here is to make the code is simple and terse as possible.

Example object:

item = { integrations: { slackData: { url: '...' } } };

EDIT 2: Thanks for pointing out the duplicates. I couldn't figure out what terms to search for. I'm probably going to go with using lodash's _.get() function.

ffxsam
  • 26,428
  • 32
  • 94
  • 144
  • have some example? what if there would be 7 levels hierarchy and we need to check if the deepest key is "truthy" ? – RomanPerekhrest Dec 15 '16 at 20:03
  • *"if there's a better way to do this kind of check in ES6"* No there isn't. There was a discussion about an operator like this but it didn't lead anywhere. – Felix Kling Dec 15 '16 at 20:04
  • @RomanPerekhrest My post includes the example.. yes. You're right, it could go 7 levels deep, and the idea is to not write out `if (a && a.b && a.b.c && a.b.c.d && a.b.c.d.e)` – ffxsam Dec 15 '16 at 20:06
  • Related: [javascript test for existence of nested object key](http://stackoverflow.com/q/2631001/218196) – Felix Kling Dec 15 '16 at 20:08
  • `data = { integrations: { slackData: { url } = {} } = {} } = item || {};`. –  Dec 15 '16 at 20:13
  • you could using something like this: `function check(o) {return function (k) { return o = o[k]; } } var result = ['integrations', 'slackData'].every(check(item));`. – Nina Scholz Dec 15 '16 at 20:31
  • @torazaburo What is expected result of the destructuring assignment at `data = { integrations: { slackData: { url } = {} } = {} } = item || {};`? `data = { a: { b: { c } = {} } = {} } = item || {};` returns same result. The assignment pattern is the same as `data = item`, no? – guest271314 Dec 16 '16 at 02:42
  • The fundamental problem here is that you are passing around malformed (partially formed) objects, requiring you to do this "null-propagation" check every time you try to access a nested property. Avoid partially formed objects, and if you do have them, then fill them in with default values as early as possible, either using ES6 defaults, if you have them, or the old stand-by of `item.integrations = item.integrations || {};` etc. –  Dec 16 '16 at 03:59

1 Answers1

-2

You can use Array.prototype.every()

var check = [item, item.integrations, item.integrations.slackData]
            .every(function(element) { return element });

Edit, Updated

As noted at comments by @FelixKling, the pattern at above using .every() will fail if item.integrations is undefined.

Given the example object at Question you can use JSON.stringify(), String.prototype.match() with RegExp /"integrations":|"slackData":|"ur‌​l":/g/, then check that .length of resulting array, if any, is equal to the number of properties expected; in the present case 3.

A javascript object which is passed to JSON.stringify() should have properties with the following pattern:

" followed by property followed by " followed by :. Depending on the source object, the RegExp can be further adjusted to meet the specific properties and values of that object.

JSON.stringify(item).match(/"integrations":|"slackData":|"ur‌​l":/g).length === 3

Note that JSON.stringify() has a replacer option which can be used to match properties of the object. The replacer function option is recursive. See also

but I'm wondering if there's a better way to do this kind of check in ES6:

The present Answer does not attempt to indicate that using JSON.stringify() and RegExp to match or filter a javascript object is "better"; but only that the approach can meet the described requirement at the present Question.

Community
  • 1
  • 1
guest271314
  • 1
  • 15
  • 104
  • 177
  • That's a cool idea. Though it's certainly not any less verbose than the code I posted. The goal is to make it far more concise. – ffxsam Dec 15 '16 at 20:03
  • 3
    That won't work if `item.integrations` doesn't exist. It doesn't make sense at all unfortunately. If that would work, then one can just write `var check = Boolean(item.integrations.slackData);`. Don't understand why this got upvotes :-/ – Felix Kling Dec 15 '16 at 20:03
  • Ah yeah, that too. You would have to make a helper function like `checkProp(item, 'item.integrations.slackData')`, and then the string would be split apart and each object carefully checked for a truthy value. – ffxsam Dec 15 '16 at 20:04
  • @ffxsam Can you include example object at Question? – guest271314 Dec 15 '16 at 20:06
  • @guest271314 Sure, done. – ffxsam Dec 15 '16 at 20:06
  • @FelixKling Good point. Could place `.every()` call in `try..catch`. – guest271314 Dec 15 '16 at 20:09
  • @guest271314 If you are going to use `try/catch`, you don't need `every` at all, but it's expensive. –  Dec 15 '16 at 20:11
  • You could do that but you don't even need `.every`. You could just write `var check = false; try { item, item.integrations, item.integrations.slackData; check = true;} catch() {};`. But how is that any better than using any `if` statement or `var check = item && ... && ...;` ? – Felix Kling Dec 15 '16 at 20:11
  • @FelixKling Did not indicate the approach as being "better" at Answer. Was in middle of editing Answer to place `.every()` call within `if` condition. You do have another point about using `&&` operator at `if` condition. – guest271314 Dec 15 '16 at 20:13
  • 1
    @FelixKling The point is, with `try/catch`, you could just say `item.integrations.slackData`. –  Dec 15 '16 at 20:15
  • Well, the question was *"I'm wondering if there's a better way to do this kind of check in ES6:"* so assuming that an answer offers a "better" approach than what the OP posted is no too far fetched ;) – Felix Kling Dec 15 '16 at 20:15
  • @torazaburo: Ah yeah, of course. – Felix Kling Dec 15 '16 at 20:16
  • @FelixKling The approach that would probably first consider taking, here, would be `JSON.stringify()` and `RegExp` to check for properties; though that approach, too, is not ES6, and would probably garner same amount of "downvote"s. There are obviously several ways to approach Question. Try to stay away from attempting to judge if something is "better" or "best"; those are very subjective terms, often requiring some form of "peer" nod and social acceptance as a "good practice", which do not rely on here, in the least as a way to gauge the "good" of something. – guest271314 Dec 15 '16 at 20:18
  • @guest271314 Using regexp on a stringified representation is a horrible idea, besides probably not even being feasible. –  Dec 15 '16 at 20:26
  • @torazaburo Why? Have we not exchanged communication on this topic previously? Not only feasible, but `JSON.stringify()` `replacer` parameter was designed for this, no? Will have to locate one of the Answers posted as to this, well-aware that the Answer could attract more "downvote". – guest271314 Dec 15 '16 at 20:27
  • @guest271314 Maybe, I don't remember. JSON is a language/grammar which is not parsable by regexp. –  Dec 15 '16 at 20:29
  • @torazaburo `JSON` is a string. Check string for "properties". Am describing two branches of approaches using `JSON.stringify()` a) using `replacer` function; b) using `RegExp` on returned string. There is a `RegExp` pattern to match property names in a stringified `javascript` object. – guest271314 Dec 15 '16 at 20:29
  • @guest271314 If you're going to propose that as a viable solution, please provide sample code that works with an object of arbitrary nesting level and multiple properties in any order. –  Dec 15 '16 at 20:31
  • @torazaburo The depth of the object does not matter. The "properties" of a `JSON` string have the same pattern. Have posted the same, here, at SO previously at Answers. Will try to locate them. – guest271314 Dec 15 '16 at 20:32
  • @torazaburo Want to find the Answer where used `RegExp` to match specifically property values of an object at a string returned by `JSON.stringify()`. Though here two approaches where used `replacer` function of `JSON.stringify()`. http://stackoverflow.com/questions/36228492/remove-object-from-nested-array, http://stackoverflow.com/questions/39262529/nested-object-and-array-destructuring/ . The object properties should always be pattern `"property":` at `JSON` string. – guest271314 Dec 15 '16 at 20:40
  • @torazaburo Two different variations that have been able to locate so far from previous attempts relating to the approach. http://stackoverflow.com/questions/37740204/convert-javascript-object-to-array-of-individual-objects/37740979#37740979 starting with `/".*"\:.*(?=,|})/g`; http://stackoverflow.com/questions/40615066/how-do-i-filter-object-and-get-a-new-object/ `let prop = \`"111"\`, re = new RegExp(prop + ":");`, `!re.test(JSON.stringify(testObj[o]))`; note template literal to preserve `"`. Not conveying that approaches are "better" or "best", only possible; and can each be improved. – guest271314 Dec 15 '16 at 21:20