Is there any reason to use if ( object != null ) in a conditional instead of the more concise if ( object ). I see the former more often, but it seems like the two are equivalent and the latter shorter.
different objects are treated differently. there are some values that can never be null and might erroneously trigger false when you don't want it to.
Booleans can never be null.
if a Boolean is defined but not given a value it is treated as false;
var bool:Boolean;
trace(bool); // false
bool = true;
trace(bool); // true
int can never be null as well.
if an int is defined but not given a value, it is treated as 0;
var i:int;
trace(i); // 0
trace(Boolean(i)); // false
i = -1;
trace(Boolean(i)); // true
i = 0;
trace(Boolean(i)); // false
i = 1;
trace(Boolean(i)); // true
Number act similar to int.
if a Number is defined but not given a value, it is treated as NaN
var num:Number;
trace(num); // NaN
trace(Boolean(num)); // false
num = -1.1;
trace(Boolean(num)); // true
num = 0;
trace(Boolean(num)); // false
num = 1.1;
trace(Boolean(num)); // true
Strings are the worst.
if a String is defined but not given a value, it is treated as null!
var str:String;
trace(str); // null
trace(Boolean(str)); // false
str = ""
trace(Boolean(str)); // false
str = "hello";
trace(Boolean(str)); // true
it is very rare in my code that i only do 'if (obj)' since most of the time there is something more specific that i truly care about.
The following code will have an object evaluate to false, even though the object is not null:
class SomeWrapper
{
var value: Object;
SomeWrapper(Object value)
{
this.value = value;
}
/// Overriden method from Object, see ActionScript 3 reference
function valueOf()
{
return value;
}
}
var myWrapper = new SomeWrapper(false);
if(myWrapper)
{
trace("myWrapper evaluates to true.");
}
else
{
trace("myWrapper evaluates to false.");
}
The else block will execute in the example above, because myWrapper evaluates to false (its valueOf method returns whatever value the wrapper contained, in this case false) even though myWrapper is not a null reference. The problem is that the above does not only test nullability of reference, it implicitly invokes valueOf method, courtesy of Flash Player virtual machine. This behavior of course may or may not be what you wanted - do you want to test whether myWrapper is a null value or whether it carries a null value? (or both perhaps).
Verbosity in this case is your friend, otherwise you gain code readability in return for potential runtime errors.
if (expression) tests the truthiness of expression by getting its boolean value. Since null and undefined are both falsy, if (object) "works" for making sure object isn't null.
Problem is, though, 0, false, and '' are also falsy. When you use if (object), the code you're trying to keep from running when it's null would also be ignored when object is zero, an empty string, or the actual boolean false. Often, that's not what you want.
If you can't guarantee that object is either null or a type other than string, number, or boolean (or their respective object types), then if (object != null) is less likely to mean something unintended.
Related
In ActionScript 3, you can check if a value exists like this:
if (object) {
trace("This object is not null, undefined, or empty!")
}
I frequently use this as a shorthand for if (object != null)
Is there a proper term for evaluating objects for null in this fashion? I suppose it's a matter of the Boolean typecasting rules for the language but I'm not sure if there's a name for the resulting syntax.
If your object is always an actual object reference, e.g. a variable of any object type, then checking if (object) is a valid way to test for nulls. If it's a property of variant type, or a dynamic property that can potentially contain simple values (ints, strings etc) then the proper way to test for null will be explicit conversion, probably even with a strict type check if (object !== null).
Like most computer languages, Ecma-script supports Boolean data types;
values which can be set to true or false. In addition, everything in
JavaScript has an inherent Boolean value, generally known as either
truthy or falsy
list of falsy values (non truthy)
false
0 (zero)
"" (empty string)
null
undefined
NaN (a special Number value meaning Not-a-Number!)
regularly for checking if a variable is null
you may use : (a == null) this statement returns true if a is null, But also return true for all of the above list, because they'r all falsy values and (a == undefined) returns true, even a is not undefined but null or 0 or false.
so you should use Identity operator in this case. following evaluations just returns true when a is null
(typeof a === "null")
// or
(a === null)
I've seen conditional statements where the condition is just a variable, which is not a boolean variable. The variable is for an object.
if (myVariable) {
doThis();
}
It seems to be checking if myVariable is null or not. Is that all it is doing? Is this good programming practice? Wouldn't it be better to do this?
if (myVariable != null) {
doThis();
}
It seems much clearer that way.
To properly answer your question:
Using an if statement with an object like that, will check if the object exists.
So if object is null or undefined it will evaluate to the equivalent of false otherwise it will be the equivalent of true.
As far as "good programming practice" goes, that is very opinion based and best left out of StackOverflow.
There is no performance hit and you will find it very common in ECMAScript based languages (like AS3 and JS) - However, many stricter languages (like C# for instance) require an explicit Boolean check so if you program in multiple languages you may find it easier to be consistent.
It's entirely up to you!
Here are some additional examples you may want to consider:
var str:String;
if(str) //will evaluate as false as str is null/undefined
if(str = "myValue") //will evaluate true, as it will use the new assigned value of the var and you're allowed to assign values inside an if condition (though it's ugly and typically uneccessary)
var num:Number;
if(num) //will evaluate as false
num = 1;
if(num) //will evaluate as true
num = 0;
if(num) //will evaluate as false since num is 0
num = -1;
if(num) //will evaluate as true
var obj:Object
if(obj) //will evaluate false
obj = {};
if(obj) //will evaluate true (even though the object is empty, it exists)
var func:Function;
if(func) //false
func = function(){};
if(func) //true - the function exists
function foo():Boolean { return false; }
if(foo) //true - the function exists
if(foo()) //false, the return of the function is false
function foo1():void { return; };
if(foo1()) //false as there is no return type
if (myVariable) // fine but not really explicit.
I usually use:
if (myVariable !== null) // more readable to me
I am using BND annotations to assist with creating a configuration managed by OSGI cm.
Here is my simple config
#Meta.AD(required = false, type = Type.Boolean, deflt = "false")
boolean enabled();
I have used the BND configuration annotation library quite a few times, but this is the first time that I would like to use a boolean type.
I have read through this
And it talks about an integer or other alternative number based handling of booleans for convenience. The thing is the deflt method always returns a string value, if my type was an integer I would do "2" (these are parsed). But booleans don't seem to be parsed in the configurable BND code up to this assignment point.
if (resultType == boolean.class || resultType == Boolean.class) {
if ( actualType == boolean.class || actualType == Boolean.class)
return o;
if (Number.class.isAssignableFrom(actualType)) {
double b = ((Number) o).doubleValue();
if (b == 0)
return false;
else
return true;
}
return true;
I would like to further know why this returns true when the deflt value is never even parsed. I expected this to more closely follow the spec and return false, since cm would try to do Boolean.parseFrom, so anything not "true" equal ignore case is false.
All of this isn't a complete failure because if I change the value through cm it works correctly after setting to true, and then false again, but obviously that was just an effort at wondering if it would ever work.
Simply I would like to know if anyone knows how to set a BOOLEAN default value using BND's configuration annotations.
Thanks
I am trying to figure out the issue, and tried different styles that I have read on Scala, but none of them work. My code is:
....
val str = "(and x y)";
def stringParse ( exp: String, pos: Int, expreshHolder: ArrayBuffer[String], follow: Int )
var b = pos; //position of where in the expression String I am currently in
val temp = expreshHolder; //holder of expressions without parens
var arrayCounter = follow; //just counts to make sure an empty spot in the array is there to put in the strings
if(exp(b) == '(') {
b = b + 1;
while(exp(b) == ' '){b = b + 1} //point of this is to just skip any spaces between paren and start of expression type
if(exp(b) == 'a') {
temp(arrayCounter) = exp(b).toString;
b = b+1;
temp(arrayCounter)+exp(b).toString; b = b+1;
temp(arrayCounter) + exp(b).toString; arrayCounter+=1}
temp;
}
}
val hold: ArrayBuffer[String] = stringParse(str, 0, new ArrayBuffer[String], 0);
for(test <- hold) println(test);
My error is:
Driver.scala:35: error: type mismatch;
found : Unit
required: scala.collection.mutable.ArrayBuffer[String]
ho = stringParse(str, 0, ho, 0);
^one error found
When I add an equals sign after the arguments in the method declaration, like so:
def stringParse ( exp: String, pos: Int, expreshHolder: ArrayBuffer[String], follow: Int ) ={....}
It changes it to "Any". I am confused on how this works. Any ideas? Much appreciated.
Here's a more general answer on how one may approach such problems:
It happens sometimes that you write a function and in your head assume it returns type X, but somewhere down the road the compiler disagrees. This almost always happens when the function has just been written, so while the compiler doesn't give you the actual source (it points to the line where your function is called instead) you normally know that your function's return type is the problem.
If you do not see the type problem straight away, there is the simple trick to explicitly type your function. For example, if you thought your function should have returned Int, but somehow the compiler says it found a Unit, it helps to add : Int to your function. This way, you help the compiler to help you, as it will spot the exact place, where a path in your function returns a non-Int value, which is the actual problem you were looking for in the first place.
You have to add the equals sign if you want to return a value. Now, the reason that your function's return value is Any is that you have 2 control paths, each returning a value of a different type - 1 is when the if's condition is met (and the return value will be temp) and the other is when if's condition isn't (and the return value will be b=b+1, or b after it's incremented).
class Test(condition: Boolean) {
def mixed = condition match {
case true => "Hi"
case false => 100
}
def same = condition match {
case true => List(1,2,3)
case false => List(4,5,6)
}
case class Foo(x: Int)
case class Bar(x: Int)
def parent = condition match {
case true => Foo(1)
case false => Bar(1)
}
}
val test = new Test(true)
test.mixed // type: Any
test.same // type List[Int]
test.parent // type is Product, the case class super type
The compiler will do its best to apply the most specific type it can based on the possible set of result types returned from the conditional (match, if/else, fold, etc.).
In this code, what values of myVar will behave as true and false?
if(myVar){}
In JavaScript for example, the following values are falsy
null
undefined
0
''
false
Object
false if the instance is null; true otherwise
String
false if the value is null or the empty string ""; true otherwise
Number, int, or uint
false if the value is NaN or 0; true otherwise
null
false
From here.
If (myVar) is a bool, then it'll obvious pass if it's true, and fail if not. If the bool was never initialized (like var myBool:Boolean; instead of var myBool:Boolean = true) then it's false by default. This same concept applies to builtin objects like Number, int etc. Pretty much for everything else, it will only pass as true if the object has been initialized through the object constructor or through a direct assignment, like so:
var a:MovieClip = new MovieClip();
var b:MovieClip = a;