Skip to main content
femkeblanco
Brainiac
September 19, 2021
Question

ExtendScript: Unexpected evaluation of "null" as second operand in logical ops

  • September 19, 2021
  • 5 replies
  • 1005 views

I've just come across an unexpected problem in the way that "null" appears to be evaluated when it's the second operand of AND or OR. All the expressions below should return "null" (but are returning the comments instead).

 

alert( true && null );  // true
alert( 1 && null );  // undefined
alert( "1" && null );  // undefined
alert( false || null );  // false
alert( 0 || null );  // undefined
alert( "" || null );  // undefined

// $.writeln( true && null );  // true
// $.writeln( 1 && null );  // undefined
// $.writeln( "1" && null );  // undefined
// $.writeln( false || null );  // false
// $.writeln( 0 || null );  // undefined
// $.writeln( "" || null );  // undefined

 

As far as I can tell, this is not the expected behaviour even in ES3. "null" appears to be evaluated as expected when it's the first operand. A quick Google search did not yield much.

 

Is there any way this can be explained?

 

Thanks in advance.

This topic has been closed for replies.

5 replies

Disposition_Dev
Community Expert
September 21, 2021

I think there might be a bit of an X/Y problem going on here. I think we're all chasing the odd behavior of null, but really we should be looking at false instead.

 

In this example, if we put null first, we get the expected value of false. That means that null is properly evaluating to false and the expression results in the other value being assigned. However, false behaves as though it's truthy. 

var d = null || false; // false
var d = false || null; // false

 

pixxxelschubser
Community Expert
September 20, 2021

I don't know. I always compare only the contents of variables - but never the values themselves.

femkeblanco
Brainiac
September 20, 2021

You're right.  And this adds to the mystery. 

 

var a = false, b = null, c = a || b;
$.writeln(c);  // null

var d = false || null;
$.writeln(d);  // false

 

Inventsable
Brainiac
September 21, 2021

Interesting find. You can actually read the specs for operators directly:

Virtually identical logic using the same operations ("GetValue" and "ToBoolean"), meaning that the following should produce the same result no matter what the data used and typeof b or c is (obeying truthy/falsy coercion) with no exception as far as I know:

 

var a = b || c;
var a = b ? b : c;

 

But as you've found this isn't the case with Extendscript!

 

var a = false || null,
    b = false ? false : null;
alert(a); // false -- Incorrect! Should be null
alert(b); // null  -- Correct

 

...Which is really odd. As every one's noticed here, null acts very strangely and doesn't seem to be coerced into Boolean correctly (maybe their internal "GetValue" and "ToBoolean" operations are not to spec and to blame?):

 

alert(true && null) // true, should be null
alert(null && true) // null, correct
alert(null
    ? true : false) // false, correct
alert(!null)        // true, correct
alert(!!null)       // false, correct

 

pixxxelschubser
Community Expert
September 20, 2021

$.writeln(false || null); // false (two falsy values with OR operator)
$.writeln(typeof false); // boolean
$.writeln(typeof null); // object
$.writeln(typeof 0); // number

 

$.writeln(!false === true); // false
$.writeln(Boolean(null)) //false
$.writeln(Boolean(0)) //false
$.writeln(Boolean("")) //false

femkeblanco
Brainiac
September 20, 2021
quote

$.writeln(false || null); // false (two falsy values with OR operator)

By @pixxxelschubser

 

But OR should return the second falsy value.  Here's what a browser returns:

 

Disposition_Dev
Community Expert
September 21, 2021

My best guess here is that a browser is likely running ES6 Javascript. But ExtendScript is basically a clone of ES3. Many things have changed between ES3 and today. But ESTK hasn't changed a bit.

 

Javascript is notorious for being inexplicable when it comes to datatypes and return values.

pixxxelschubser
Community Expert
September 20, 2021

I'm sorry, but I don't know what you're trying to do.

Can you explain a bit more in detail, please?

 

There are the only six values that are considered to be falsy values in Javascript.

false

undefined

null

""(empty string)

NaN

0

 

Truthy and Falsy values are the non-boolean values that are coerced to true
or false when performing certain operations.

 

 

 

 

function nullCheck (a, b) {
var value1 = a;
var value2 = b;

var result = value1 || value2; 

$.writeln(result); // REMEMBER, the OR operator ALWAYS returns the first TRUTHY value
}

nullCheck (1, 21); // 1
nullCheck ("2", 22); // 2
nullCheck (true, 23); // true
nullCheck (false, 24); // 24
nullCheck (undefined, 25); // 25
nullCheck (null, 26); // 26
nullCheck ("", 27); // 27
nullCheck (NaN, 28); // 28
nullCheck (0, 29); // 29
nullCheck (30, null); // 30
nullCheck ("31", null); // 31
nullCheck (true, null); // true
nullCheck (null, true); // true

 

 

 

 

 

 

femkeblanco
Brainiac
September 20, 2021

At this point, I'm just trying to explain the peculiar behaviour. 

 

What do you get when you directly write these two expressions? 

 

$.writeln(false || null);
$.writeln(0 || null);

 

 

CarlosCanto
Community Expert
September 19, 2021

Hi, I don't have an explanation for your question.

 

but, are you trying to return true or false? or default values?

 

there are ways of doing both scenarios

 

for true or false, use the double NOT operator

 

alert(!!(1 && null)); // false
alert(!!(null && 1)); // false

alert(!!("1" && null)); // false
alert(!!(0 || null)); // false
alert(!!("1" || null)); // true
alert(!!("" || null)); // false

 

 

femkeblanco
Brainiac
September 20, 2021

Thanks, @CarlosCanto.  I was trying to return null but was getting undefined.  It's not a problem, I can use undefined instead.  But when I looked into it, I found the above.  Firstly, I found it surprising that they could have gotten this wrong, after all it's a basic value type in a basic operation.  Secondly, I wondered what the explanation could be.