Just read this highly-related question, and then reflected on what I was using in my own code base for a project at work.
I wrote a simple function to demonstrate this question (using Google Apps Script, thus the calls to Logger.log()):
function emptyValueTest() {
var object = {
prop1: "real_data",
prop2: "",
prop3: undefined,
prop4: null
}
// What I have used in my code personally. All evaluate to TRUE
if (object.prop2 === "") Logger.log("prop2 was empty");
if (typeof object.prop3 === "undefined") Logger.log("prop3 was undefined");
if (object.prop4 === null) Logger.log("prop4 was null");
// The other solution I've seen. All evaluate to FALSE
if (object.prop2) Logger.log("prop2 was empty");
if (object.prop3) Logger.log("prop3 was undefined");
if (object.prop4) Logger.log("prop4 was null");
}
I've been building a system for the past few months with thousands of lines of code, and I often find myself back-tracking when I see a particular value, to remember what it's previous state was before a particular conditional expression.
Since I'm the one writing the code it isn't too difficult for me to figure it out, because I know the structure of the data, the values that are supposed to be there, etc.
However, this system will be taken over by another developer after I graduate from my university, so I wonder what the best practice is for representing that a property has no data.
For example, my use case is that I have event Objects which are initialized with empty data and, during the lifetime of a semester, are eventually filled with real data. Personally I use undefined because it makes more sense to me to read if (typeof data === "undefined"), having a similar semantic meaning to "if this data is undefined" (i.e. no value yet).
But I wonder, in industry, in libraries, and in personal projects, what are commonly-used methods to make code more readable, understandable? Though the length of the first three conditionals is longer than the latter three, I find the latter three to be ambiguous.
For example, prop2 could have a non-empty string like "data", or the value true, which would cause the latter conditional if (object.prop2) to evaluate to true in both cases, because everything in JavaScript is truthy except the following:
- null
- undefined
- NaN
- empty string ("")
- 0
- false
And it is entirely possible that data could have "", 0, and false as valid values, whereas null, undefined and (especially) NaN are probably not typical values for real data.
Obviously I we know the structure of the data then we might impose more strict checks to disambiguate non-empty strings from true. But in a project with thousands of lines of code it seems to me that this gets out of hand fast, especially if the structure of the data changes over time.
So my question: Is there a preferred method of representing empty values in Javascript? And is there a particular reason for the preference (performance, readability, scalability, etc.)?
null, to differentiate easily between properties that have not been defined, compared to ones that have yet to been used or set.NaNcould result from some screwed up maths that fails, and it'd be much harder to tell where it's coming from (because it'd be treated as empty). Also, an added bonus is thatnullcan only result when you either assign a variable to the property that is null already, or you directly assign null. You can't get null any other way (except probably througheval('null'), but it's so unlikely).var split = "some,".split(", "); the value atsplit[1]would benull, which, depending on the system might be a valid value. That's why I lean towardundefined, because semantically it makes more sense, and there's less chance of random collision like in the example I just gave. I wonder if that's the consensus though...split[1] === undefined. Anway, I'd usenulltoo.undefinedis used for properties that are not defined. But those properties are indeed defined... with no value. Then you should usenull, since it's its precise meaning.match()and some DOM methods do return null, which I forgot about. But the other points still stand.undefinedyou don't know whether that's because it hasn't been assigned a value or has been assigned theundefinedvalue. Just set values to whatever suits and deal with them when you read them. Don't make state an issue.