0

I'm reviewing this line of code. It has an expression that looks like this:

!args.value || args.value.length

For example suppose we do this:

let v = {};
console.log(!v.value);  //logs true
console.log(v.value);  //logs undefined
console.log(v.value.length); //Script wont run - cannot read property length of undefined

So even though value is undefined, we are proceeding to check that args.value.length (or undefined> is less than the constraint? So effectively we could be checking something like this ( IIUC ):

    true             throws
!undefined || undefined.length < 4

So I thought the purpose of the first check in the statement was to make sure that the undefined is actually defined?

So in other words it should be args.value && args.value.length? Or stated differently:

if args.value exists, then check the length of it?

Here's the entire snippet in context just for completeness:

if (isMinLength && (!args.value || args.value.length < args.constraints[0])) {
return eachPrefix + "$property must be longer than or equal to $constraint1 characters";
Ole
  • 41,793
  • 59
  • 191
  • 359
  • If `args.value` is falsy then that error holds (it's not longer, because there's nothing there). Or, if the length is less than the constraint, then that error holds too... Am I missing something? The second condition would only be evaluated if the previous is falsy, which would happen if `args.value` is truthy – pushkin Jun 12 '18 at 15:52
  • The condition is correct. `args.value` is optional and `args.value.length` is checked only if `args.value` is set. If it is not set the the test passes (no limit set). Changing it as you suggest makes `args.value` required. – axiac Jun 12 '18 at 16:12

2 Answers2

3

The < has higher precedence than ||:

if (isMinLength && (!args.value || (args.value.length < args.constraints[0]))) {
//                                 ^                                       ^

So the condition matches if either args.value doesn't exist, or when its .length is too small.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • I'm still a bit puzzled, because if args.value is undefined, then args.value.length will throw an unchecked exception right? I also updated the question to reflect this concern. But judging by your SO score, I"m probably missing something ... – Ole Jun 12 '18 at 16:29
  • @Ole If `args.value` is falsy and `!args.value` evaluates to `true`, the right hand side [won't be evaluated at all](https://stackoverflow.com/questions/12554578/does-javascript-have-short-circuit-evaluation). – Bergi Jun 12 '18 at 17:22
  • Oooh ... Got it ... OK Thanks! – Ole Jun 12 '18 at 17:26
1

At first its actually

!args.value || (args.value.length < args.constraints[0])

But you are right, the only difference to

args.value && args.value.length < args.constraints[0]

Is that the first always returns false while the second returns undefined if args.value is not defined. As you use that in an if statement, the outcome doesnt really matter.

Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151