What is this ternary expression doing? - javascript

I have a function I'm testing that takes two arguments Definition and Element, and has a ternary statement in it that goes like
otherThingName: (_.has(Definition.thing, 'thingName') ? Element[Definition.thing.thingName] : null)
Now Definition.thing.thingName will exist, but Element does not have a property named Definition.
Is that property being set on Element while at the same setting otherThingName?

A ternary expression is sort of a short hand if/else, so in the first instance, its testing the statement (_.has(Definition.thing, 'thingName').
I don't work with underscore, but it looks like this test is checking if Definition.thing has a property of thingName.
If this comes back true, it will set otherThingName to be Element[Definition.thing.thingName].
Otherwise it will set it to null.
Element[Definition.thing.thingName] is looking at an object called Element, and pulling back the property with the key matching the value of Definition.thing.thingName.
For example, if
Definition.thing.thingName == "name",
Element[Definition.thing.thingName] == Element["name"] == Element.name.
Hope this helps.

Expanding out the text it becomes a bit more clear:
var str;
if (_.has(Definition.thing, 'thingName')) {
str = Element[Definition.thing.thingName]
} else {
str = null;
}
...
otherThingName: str
It looks like it is defining the member of some object 'otherThingName' to be either whatever Element has set for field Definition.thing.thingName if that exists, or null otherwise.

Related

How to set a value to a variable inside ternary

Is it possible to set the value of a variable inside a ternary based on a state change?
Something like:
{ this.state.change ? myObj.changeIt = true : null }
writing it like this returns an error: Assignment to property of function parameter 'myObj'
You need parenthesis for an assignment inside of a ternary, because you have some expressions left hand side.
this.state.change ? (myObj.changeIt = true) : null;
Beside that, you better take a imperative style.
if (this.state.change) myObj.changeIt = true;

JavaScript get condition text (or array of values) of ternary's condition operator

[wasn't sure how to word this question exactly, but] say I have some code:
var myValue = 6;
var newValue = myValue == 6 ? myValue : 3;
notice that I'm using the ternary operator to check if a variable fulfils a certain condition, and if so, then I set my newValue to that variable, and if not, something else.
So the (slight) problem:
In a case like this, I have to actually write the variable name twice (myValue == 6 ? myValue : ...), this usually isn't a problem, but say I have a very long variable name, or even the property of a certain array or something else I don't want to manually write out, or even make a new variable; I just want to set the new variable equal to the value of the variable in the condition.
If my condition is simply if the expression exists, then I could obviously do:
newValue = myValue || 3;
but if I'm checking any other condition, I have to write the checking-variable twice, so is there any way to access the ternary's condition text, at least, or even an array of the variables involved in the condition so I have some kind of hope to access it, or is there any other way to do one-line conditions like this, without assigning a new variable?

In ES2015 is there a way to directly access object properties without checking for undefined?

In ES5 whenever I want to get some property I need to first check that it exists like this:
if (typeof floob.flib !== 'undefined') {
// do something
}
even worse is that for nested properties you have to manually check for the existence of every property down the dotted path.
Is there a better way to do this in ES2015?
If it is just a single depth property name - you don't need typeof, you may just compare the value with undefined.
Your solution is prone to false negatives: it may think there is no a property with a given name, while there is one. Example: var o = { foo: undefined };
If you need to check if the path exists in the nested objects - you still need to implement recursion/loop/or use any library that does either for you.
ES2015 did not bring anything new to solve this problem easier.
If you have lodash available, you can use _.get(obj, path, defaultValue) (https://lodash.com/docs#get)
By using typeof,
typeof floob.flib === 'undefined'
equals to,
floob.flib === undefined
I assume you want to check whether floob.flib has a value, and if it does, you want to perform an operation with it.
However, in JS, there's almost simpler way to achieve this.
E.g.
if (floob.flib) {
// 'floob.flib' is NOT 'null', 'empty string', '0', false or 'undefined'
}
This also works well if you want to assign variable with ternary ( ?: ) operators.
var str = floob.flib ? 'exists' : 'does not exist';
Or even using logical OR ( || )
var str = floob.flib || '<= either null, empty, false, 0 or undefined';
Note that unless floob.flib does not produce ReferenceError exception, the code above should work just fine.

JavaScript progressive undefined checks

Let's say I have the following code:
var t = $("#objectID").html();
Checking that t is defined and has a proper value is easy.
if (typeof(t) === 'undefined' || t == null || t == '')
t = 'something else';
OR
var t = $("#objectID").html() || 'something else';
My question is though, what if you have something like the following: How would would you check it for undefined values before continuing?
$("#object").find("element").html().replace(/ |t/g, '').trim();
How do I ensure that each part of the object is legitimate before continuing down the line without having a large block of checks?
What if there's many things similar to .replace and .trim, like 10 or so? How do you check for each one?
You can use the function parameter of .html()
$("#object").find("element").html(function(html){
return ((html || 'Something').replace(/ |t/g, '') || 'Something else').trim();
});
So, what you are doing is first you're checking html has value and give it some default value if it doesn't have one. Then you group the returned string from replace and check if it has truthy value or give it a default value too and then trim it.
Here's how I would do that, checking as needed.
var element = $("#object").find("element");
var t = element.length ? element.html() : '';
t = t.replace(/ |t/g, '').trim();
First step is making a variable called element to save the jQuery object. Anytime you use the same jQuery search more than once, it's a good idea to save it to a variable: it avoids repetition and speeds up performance.
The next step is calling jQuery's length method to test if it really found any HTML elements. If either "#object" or "element" are not found, element becomes an empty jQuery object with a length of 0, and 0 is considered false in a JavaScript conditional check.
If the length of element is at least 1, then we know it's legitimate, and call safely html() on it.
If length is 0, then t is just set to an empty string. Checking length was necessary because calling html() on an empty jQuery object would have returned undefined instead of a string and caused an error.
I used the ? conditional operator for brevity but you can do the exact same check with an if statement
var element = $("#object").find("element");
if (element.length) {
var t = element.html();
} else {
var t = '';
}
t = t.replace(/ |t/g, '').trim();
I like making t default to an empty string, to ensure the variable is always a string. That way I can call replace() or trim() or any other string method with it.
An empty string also evaluates to false in JavaScript conditions, making it easy to check later on.
if (t) {
doSomethingWith(t);
}

javascript 'short hand' notation in cycle plugin

I found this while going through some cycle plugin options:
$('#prev')[index == 0 ? 'hide' : 'show']()
I hate to admit but i'm having a hard time expanding this into it's 'long' form.
I know that if index is 0 element gets hidden otherwise it's visible.
It's the $('#prev')[index == 0 that is tripping me up :-(
Normally, you would write either $("#prev").hide() or $("#prev").show() depending on what you want to do.
However, you can access properties on objects by using square brackets [] with the property name as a string - among other things, this allows for object keys that contain characters that wouldn't be valid otherwise. Even something like obj["some property name"] would be valid here.
So basically, what your ternary operator is doing is choosing whether to get the show or hide string, which is then used to retrieve that property of the jQuery object (in this case, the methods) and calling them.
To make it simple for you, the code below:
$('#prev')[index == 0 ? 'hide' : 'show']();
is same as doing:
if (index == 0) {
$('#prev').hide();
} else {
$('#prev').show();
}
All that's really happening here is a test on the index variable. If it is equal to zero then the element is being hidden, otherwise it is being shown:
var elem = $('#prev');
if ( index == 0 ) {
elem.hide();
} else {
elem.show();
}
The 'hide' and 'show' strings are merely the names of the functions. Which function needs to be called is decided by the ternary conditional statement. Both of those functions are functions of the element and therefor you call them on the actual element. The brackets at the end of the statement is what actually calls the function.

Categories