Most of the modern languages like Ruby, Python or Java have a single null value ( or ), which seems a reasonable approach.
Some native methods like can return to denote a missing object. Take a look at the sample:
Often such risky actions generate related errors, ending the script lightning fast. Related common error messages are:
- and alike type errors.
To reduce the risk of such errors, you have to understand the cases when is generated. And more important suppress its appearance and spread within your application, increasing code durability.
Let's detail the exploration of and its effect on code safety.
1. What is
- Boolean: or
- Number: , ,
- Symbol: (starting ES2015)
- Undefined: .
And a separated object type: , .
From 6 primitive types is a special value with its own type Undefined. According to ECMAScript specification:
Undefined value primitive value is used when a variable has not been assigned a value.
The standard clearly defines that you will receive an undefined value when accessing uninitialized variables, non existing object properties, non existing array elements and alike. For instance:
The above example demonstrates that accessing:
- an uninitialized variable
- a non-existing object property
- or a non-existing array element
are evaluated to .
The ECMAScript specification defines the type of value:
Undefined type is a type whose sole value is the value.
In this sense, operator returns string for an value:
Of course works nicely to verify whether a variable contains an value:
2. Common scenarios that create
2.1 Uninitialized variable
A declared variable that is not yet assigned with a value (uninitialized) is by default .
Plain and simple:
is declared and not yet assigned with a value. Accessing the variable evaluates to .
An efficient approach to solve the troubles of uninitialized variables is whenever possible assign an initial value. The less the variable exists in an uninitialized state, the better. Ideally you would assign a value right away after declaration , but this is not always possible.
Tip 1: Favor , otherwise use , but say goodbye to
In my opinion, one of the best features of ECMAScript 2015 is the new way to declare variables using and . It is a big step forward that these declarations are block scoped (contrary to older function scoped ) and exist in a temporal dead zone until the declaration line.
When the variable receives a value once and forever, I recommend to use a declaration. It creates an immutable binding.
One of the nice features of is that you have to assign an initial value to the variable . The variable is not exposed to the uninitialized state and to access is simply not possible.
Let's check the function that verifies whether a word is a palindrome:
and variables are assigned with a value once. Seems reasonable to declare them as , since these variables are not going to change.
If you need to rebind the variable (i.e. assign multiple times), apply a declaration. Whenever possible assign an initial value to it right away, e.g. .
What about the old school ? In terms of ES2015, my suggestion is stop using it at all.
declaration problem is the variable hoisting in the entire function scope. You can declare a variable somewhere at the end of the function scope, but still it can accessed before declaration: and you'll get an .
is accessible and contains even before the declaration line: .
Contrary, a (including ) variable cannot be accessed before the declaration line. It happens because the variable is in a temporal dead zone before the declaration. And that's nice, because you have less chances to access an .
The above example updated with (instead of ) throws a , because the variable in the temporal dead zone is not accessible.
Encouraging the usage of for immutable bindings or otherwise ensures a practice that reduces the uninitialized variables appearance.
Tip 2: Increase cohesion
Cohesion characterizes the degree to which the elements of a module (namespace, class, method, block of code) belong together. The measurement of the cohesion is usually described as high cohesion or low cohesion.
High cohesion is preferable because it suggests to design the elements of the module to focus solely on a single task. It makes the module:
- Focused and understandable: easier to understand what the module does
- Maintainable and easier to refactor: the change in the module affects fewer modules
- Reusable: being focusing on a single task, it makes the module easier to reuse
- Testable: you would easier test a module that's focused on a single task
High cohesion accompanied with loose coupling is the characteristic of a well designed system.
A code block by itself might be considered a small module. To profit from the benefits of high cohesion, you need to keep the variables as close as possible to the code block that uses them.
For instance, if a variable solely exists to form the logic of a block scope, then declare and allow the variable to live only within that block (using or declarations). Do not expose this variable to the outer block scope, since the outer block shouldn't care about this variable.
One classic example of unnecessary extended life of variables is the usage of cycle inside a function:
, and variables are declared at the beginning of function body. However they are used only near the end. So what is the problem with such approach?
All the way between the declaration at the top and the usage in statement the variables , are uninitialized and exposed to . They have an unreasonably long lifecycle in the entire function scope.
A better approach is to move these variables as close as possible to their usage place:
and variables exist only in the block scope of statement. They don't have any meaning outside of .
variable is declared close to the source of its usage too.
Why is the modified version better than the initial one? Let's see:
- The variables are not exposed to uninitialized state, thus you have no risk of accessing
- Moving the variables as close as possible to their usage place increases the code readability
- High cohesive chunks of code are easier to refactor and extract into separated functions when necessary
2.2 Accessing non-existing property
Let's demonstrate that in an example:
is an object with a single property . Accessing a non-existing property using a property accessor is evaluated to .
By itself accessing a non-existing property does not throw an error. The real problem appears when trying to get data from a non-existing property value. This is the most common related trap, reflected in the well known error message .
Let's slightly modify the previous code snippet to illustrate a throw:
does not have the property , so evaluates to .
As result, accessing the first item of an value using the expression throws a .
Unfortunately you often don't have control over the objects that you work with. Such objects may have different set of properties in diverse scenarios. So you have to handle all these scenarios manually.
Let's implement a function that adds at the beginning and/or at the end of an array new elements. parameter accepts an object with properties:
- : element inserted at the beginning of
- : element inserted at the end of .
The function returns a new array instance, without altering the original array (i.e. it's a pure function).
The first version of , a bit naive, may look like this:
Because object can omit or properties, it is obligatory to verify whether these properties exist in .
A property accessor evaluates to if the property does not exist. The first temptation to check weather or properties are present is to verify them against . Let's do the verification in conditionals and ...
Not so fast. There is a serious drawback in this approach. , as well as , , , and are falsy values.
In the current implementation of , the function doesn't allow to insert falsy elements:
and are falsy. Because and actually compare against falsy, these elements are not inserted into the array. The function returns the initial array without modifications.
The tips that follow explain how to correctly check the property existence.
Tip 3: Check the property existence
- : compare against directly
- : verify the property value type
- : verify whether the object has an own property
- : verify whether the object has an own or inherited property
My recommendation is to use operator. It has a short and sweet syntax. operator presence suggests a clear intent of checking whether an object has a specific property, without accessing the actual property value.
is a nice solution too. It's slightly longer than operator and verifies only in object's own properties.
The 2 ways that involve comparing with might work... But it seems to me that and look verbose and weird, and expose to a suspicions path of dealing directly with .
Let's improve function using operator:
(and ) is whether the corresponding property exists, otherwise.
The usage of operator fixes the problem with inserting falsy elements and . Now, adding these elements at the beginning and at the end of produces the expected result .
Tip 4: Destructuring to access object properties
When accessing an object property, sometimes it's necessary to indicate a default value if the property does not exist.
You might use accompanied with ternary operator to accomplish that:
The usage of ternary operator syntax becomes daunting when the number of properties to check increases. For each property you have to create a new line of code to handle the defaults, increasing an ugly wall of similar looking ternary operators.
In order to use a more elegant approach, let's get familiar with a great ES2015 feature called object destructuring.
Object destructuring allows inline extraction of object property values directly into variables, and setting a default value if the property does not exist. A convenient syntax to avoid dealing directly with .
Indeed, the property extraction now looks short and meaningful:
To see things in action, let's define an useful function that wraps a string in quotes.
accepts the first argument as the string to be wrapped. The second argument is an object with the properties:
- : the quote char, e.g. (single quote) or (double quote). Defaults to .
- : the boolean value to skip quoting if the string is already quoted. Defaults to .
Applying the benefits of the object destructuring, let's implement :
destructuring assignment in one line extracts the properties and from object.
If some properties are not available in object, the destructuring assignment sets the default values: for and for .
Fortunately, the function still has room for improvements.
Let's move the destructuring assignment right into the parameters section. And set a default value (an empty object ) for parameter, to skip the second argument when default settings are enough.
Notice that a destructuring assignment replaces the parameter in function's signature. I like that: becomes one line shorter.
on the right side of destructuring assignment ensures that an empty object is used if the second argument is not specified at all .
Object destructuring is a powerful feature that handles efficiently the extraction of properties from objects. I like the possibility to specify a default value to be returned when the accessed property doesn't exist. As result, you avoid and the problem related to handling it.
Tip 5: Fill the object with default properties
If there is no need to create variables for every property like the destructuring assignment does, the object that misses some properties can be filled with default values.
The ES2015 copies the values of all enumerable own properties from one or more source objects into the target object. The function returns the target object.
For instance, you need to access the properties of object, which not always contains its full set of properties.
To avoid when accessing a non-existing property from , let's make some adjustments:
- Define an object that holds the default property values
- Call to build a new object . The new object receives all properties from , but the missing ones are taken from .
contains only property. object defines the default values for properties and .
takes the first argument as a target object . The target object receives the value of property from source object. And the value of property from source object, because doesn't contain .
The order in which the source objects are enumerated does matter: later source object properties overwrite earlier ones.
You are now safe to access any property of object, including that wasn't available in initially.
Instead of invocation, use the object spread syntax to copy into target object all own and enumberable properties from source objects:
The object initializer spreads properties from and source objects. The order in which the source objects are specified is important: later source object properties overwrite earlier ones.
Filling an incomplete object with default property values is an efficient strategy to make your code safe and durable. No matter the situation, the object always contains the full set of properties: and cannot be generated.
2.3 Function parameters
The function parameters implicitly default to .
Normally a function that is defined with a specific number of parameters should be invoked with the same number of arguments. In such case the parameters get the values you expect:
The invocation makes the parameters and receive the corresponding and values. The multiplication is calculated as expected: .
What does happen when you omit an argument on invocation? The parameter inside the function becomes .
Let's slightly modify the previous example by calling the function with just one argument:
is defined with two parameters and .
The invocation is performed with a single argument: as result parameter is , but parameter is .
Tip 6: Use default parameter value
Sometimes a function does not require the full set of arguments on invocation. You can simply set defaults for parameters that don't have a value.
Recalling the previous example, let's make an improvement. If parameter is , it gets assigned with a default value of :
The function is invoked with a single argument . Initially parameter is and is .
The conditional statement verifies whether is . If it happens, assignment sets a default value.
While the provided way to assign default values works, I don't recommend comparing directly against . It's verbose and looks like a hack.
A better approach is to use the ES2015 default parameters feature. It's short, expressive and no direct comparisons with .
Modifying the previous example with a default parameter for indeed looks great:
in the function signature makes sure that if is , the parameter is defaulted to .
ES2015 default parameters feature is intuitive and expressive. Always use it to set default values for optional parameters.
2.4 Function return value
function does not return any computation results. The function invocation result is .
The same situation happens when statement is present, but without an expression nearby:
statement is executed, but it doesn't return any expression. The invocation result is also .
Of course, indicating near the expression to be returned works as expected:
Now the function invocation is evaluated to , which is squared.
Tip 7: Don't trust the automatic semicolon insertion
- empty statement
- , , , , declarations
- expression statement
- statement, statement
If you use one of the above statements, be sure to indicate a semicolon at the end:
At the end of both declaration and statement an obligatory semicolon is written.
What happens when you don't want to indicate these semicolons? For instance to reduce the size of the source file.
In such situation ECMAScript provides an Automatic Semicolon Insertion (ASI) mechanism, which inserts for you the missing semicolons.
Being helped by ASI, you can remove the semicolons from the previous example:
There is one small, but annoying trap created by ASI. When a newline stands between and the returned expression , ASI automatically inserts a semicolon before the newline .
What does mean inside a function to have statement? The function returns . If you don't know in details the mechanism of ASI, the unexpectedly returned is misleading.
For instance, let's study the returned value of invocation:
The statement makes the function to return instead of the expected array.
The problem is solved by removing the newline between and array literal:
My recommendation is to study how exactly Automatic Semicolon Insertion works to avoid such situations.
Of course, never put a newline between and the returned expression.
evaluates the expression and returns no matter the result of evaluation.
One use case of operator is to suppress expression evaluation to , relying on some side-effect of the evaluation.
3. in arrays
You get when accessing an array element with an out of bounds index.
array has 3 elements, thus valid indexes are , and .
Because there are no array elements at indexes and , the accessors and are .
When a gap (aka empty slot) is accessed inside a sparse array, you also get an .
The following example generates sparse arrays and tries to access their empty slots:
is created corresponding by invoking an constructor with a numeric first argument. It has 3 empty slots.
is created with an array literal with the missing second element.
In any of these sparse arrays accessing an empty slot evaluates to .
When working with arrays, to escape catching , be sure to use valid array indexes and avoid at all creating sparse arrays.
4. Difference between and
A reasonable question appears: what is the main difference between and ? Both special values imply an empty state.
The main difference is that represents a value of a variable that wasn't yet initialized, while represents an intentional absence of an object.
Let's explore the difference in some examples.
The variable is defined, however is not assigned with an initial value:
variable is , which clearly indicates an uninitialized variable.
The same uninitialized concept happens when a non-existing object property is accessed:
In other cases you know that a variable expects to hold an object or a function to return an object. But for some reason you can't instantiate the object. In such case is a meaningful indicator of a missing object.
However might be invoked with a non-object argument: or (or generally a primitive value, or ). In such case the function cannot create a clone, so it returns - the indicator of a missing object.
operator makes the distinction between the two values:
The strict quality operator correctly differentiates from :
- uninitialized variables
- non-existing object properties or methods
- out of bounds indexes to access array elements
- the invocation result of a function that returns nothing
Mostly comparing directly against is a bad practice, because you probably rely on a permitted but discouraged practice mentioned above.
An efficient strategy is to reduce at minimum the appearance of keyword in your code. In the meantime, always remember about its potential appearance in a surprising way, and prevent that by applying beneficial habits such as:
- reduce the usage of uninitialized variables
- make the variables lifecycle short and close to the source of their usage
- whenever possible assign an initial value to variables
- favor , otherwise use
- use default values for insignificant function parameters
- verify the properties existence or fill the unsafe objects with default properties
- avoid the usage of sparse arrays
I guess we can file this one under “Everybody Has to Start Somewhere.” I don’t want to make Antonio Margheriti out to be some sort of unappreciated genius of science fiction cinema or anything, but his mature work in the genre— even the fairly dismal Planet on the Prowl— exhibits a degree of style, enthusiasm, whimsy, and most of all personality that is simply nowhere to be found in Assignment Outer Space. In this film, his first as a solo director, Margheriti seems bound to a set of expectations that he is ill-suited to fulfill. Unlike every subsequent Italian space opera that I’ve ever seen, Assignment Outer Space wants very badly to be taken as seriously as, say, Destination Moon or Conquest of Space. Ennio De Cocini’s script (written under the pseudonym Vassilij Petrov— given Stanslaw Lem’s recent rise to international prominence, I wonder if the Russian-sounding name was a legitimacy scam along the same lines as the faux-British aliases so popular among Italian filmmakers working in Hammer-inspired Gothic horror) therefore has no place for such baroque embellishments as off-world clone factories, alien possession conspiracies, living rogue planets, or diabolical space yetis. Its hero is not particularly square-jawed, and he just barely qualifies as one-fisted. Even its sexy female astronaut is but a faint foreshadowing of her sisters to come. Yet a close examination reveals Assignment Outer Space to be no less half-assed or far-fetched than the Gamma 1 tetralogy, so all the striving after respectability accomplishes little but to deprive this movie of appeal that it might otherwise have offered.
That one-fisted man of inaction I mentioned is Ray Peterson (Rik Van Nutter, of Hard Times for Vampires and Colossus and the Huns), a journalist on the staff of the Interplanetary Chronicle of New York. On December 17th, 2116, Peterson’s editor sends him out to Space Station ZX-34, in Galaxy M-12, to report on the station crew’s investigation of anomalous infrared emissions in their sector of space. Here in act one, that’s a very long trip— long enough to require the Interplanetary Chronicle to book passage for Peterson aboard the sleeper ship BZ-88. Later on, though, De Cocini will forget all about that, and treat the return voyage to Earth’s neighborhood as no more strenuous an undertaking than a jaunt to the corner bar. He’ll also forget about those infrared emissions, which is just as well, frankly. Trying to puzzle out the ramifications of general relativity for the 24-hour news cycle was making my brain sore.
Anyway, Al (Archie Savage, from Virgin of the Jungle and the Franco-Italian The Thief of Baghdad) and Archie (Alain Dijon, of The Invisible Dr. Mabuse and The Testament of Dr. Mabuse), the pilot and navigator respectively of the BZ-88, give Ray a raft of shit about his inexperience with travel in deep space, and about his fundamental superfluity to any of the work that will go on either aboard the ship or on the space station, but their prickly attitudes are mostly a put-on. The same cannot be said of George (David Montressor), the commander of Station ZX-34, however. George is openly resentful of Peterson’s presence, regarding the reporter as at best a toddler in need of babysitting, and at worst a spy in need of vigilant policing. Indeed, the commander’s sullen suspiciousness is not allayed even when Peterson saves the life of Crewmember Y-13— also known as George’s girlfriend, Lucy (Gaby Farinon, of Blood and Roses)— during the extravehicular excursion necessary for refueling the BZ-88. For one thing, Peterson wasn’t supposed to be outside the station at all, and he certainly didn’t have George’s permission to film the refueling operations. And for another, while shoving Lucy out of the path of that meteor, Ray propelled himself straight into the fuel line, dislodging it from its port in the ship’s boost stage and spilling 500 gallons of neohydrozene propellant before the station’s crew could shut off the pumps. While chewing the reporter out afterwards, George directly states that he considers the orderly functioning of his space station and the conservation of its resources to be of far greater importance than a single human life.
Mind you, Peterson doesn’t know yet that Crewmember Y-13 is Station ZX-34’s only woman, and he certainly has no idea about her relationship with the commander. After all, one person in a space suit looks more or less exactly like any other. Their proper meeting shortly after the rescue is practically the Platonic Ideal of the “But… you’re a girl!” scenes that were so beloved by the writers of crappy sci-fi movies during the middle of the last century. For one thing, Gaby Farinon and Rik Van Nutter fail as completely to establish the chemistry between Lucy and Ray that will supposedly be so important later on as any pair of actors I’ve ever seen. And better yet, Peterson actually says, “But… you’re a girl!” the first time he sees Lucy without her space suit. It’s honestly sort of charming to see a movie commit to sucking like that.
Now George has been acting from the word go as if he were hiding something nefarious out there on Station ZX-34, and with his unapologetically cavalier attitude toward the lives of his crew, you’re probably expecting Assignment Outer Space’s plot (once it finally deigns to put in an appearance) to concern Peterson discovering the commander’s secret and using his position with the Interplanetary Chronicle to bring him to justice. That might even have been where De Cocini thought the story was headed, too, when he started writing. If so, the premise held his attention no better than that radiation Ray was sent up to write about, for George now receives orders from the High Command to embark for Mars aboard the BZ-88. At first, the commander plans on leaving both Ray and Lucy behind on the station, but that doesn’t last very long. On the one hand, Peterson pulls some strings via the Chronicle to get himself attached to George’s hush-hush mission, and on the other, Lucy effortlessly convinces her boss/ boyfriend that a trained navigator (which is to say, Lucy) is the last person the commander ought to be cutting from the crew in order to make room for the reporter.
So what’s this mission to Mars all about? Well, the rocketship A-2 has suffered some sort of computer malfunction on its voyage home from someplace or other. The crew are dead in their hibernation chambers, the autopilot isn’t accepting outside commands, and unless something happens to knock it off its present course, the ship will follow its programming until it falls into orbit around Earth. Normally that would be exactly what the High Command wants, but the A-2 was a testbed for a new type of propulsion based on photonic energy (or maybe protonic energy— the cast is sharply divided on the subject, and a few of them are even adamant that the A-2’s engines use potonic energy), and the engines are behaving even worse than the computer. Somehow, the photonic energy is feeding back through the ship’s shields, projecting a curtain of irresistible heat around the A-2 at a radius of 5000 miles. The Earth’s radius, meanwhile, is a bit less than 4000 miles, and the A-2’s computer is programmed to take up its orbit 1500 miles above the surface. It won’t take the A-2 very many orbits to bake the entire planet, so obviously somebody had better intercept the wayward ship and either destroy it or send it off someplace else where it won’t bother anyone. You might ask what the hell kind of sense it makes to entrust this urgent undertaking to a ship that is currently orbiting a starbase in another fucking galaxy, but it’s probably better not to.
George and his crew get a small taste of the A-2’s power when they encounter the Moon-based rocket MS-13 in the vicinity of Mars. That ship was barely nicked by the A-2’s shields, and it’s now dead in space with blown-up fuel tanks, a melted boost stage, and a dead engineer. The MS-13 crash-lands on Phobos before the BZ-88 can intervene, but the latter vessel does manage to rescue one survivor afterwards. There’s no sign of the A-2 anywhere near Mars now, so the BZ-88 hurries ahead to Venus instead, where the crew can assist the personnel of a military outpost equipped with an arsenal of nuclear missiles. Naturally, the missiles fare no better against the A-2’s bubble of death than the Moon rocket, but Al notices something interesting about the fate that befalls the second one fired. It was able to approach nearly twice as close to its target before being destroyed, which suggests that the A-2’s heat field is discontinuous. An old warship, the TS-13, is part of the Venus garrison, and Al proposes to take it up to a position from which he might be able to fire a nuclear warhead straight through the gap.
I have two favorite moments in Assignment Outer Space, both of them instances in which something has gone catastrophically wrong, but it isn’t initially apparent exactly what or how. The first comes when the MS-13 smashes into the surface of Phobos. It’s immediately obvious that this is an extraordinarily ill-edited scene, and that a disembodied stock-footage explosion has been tossed in to represent the spaceship’s destruction. More importantly, though, there’s something ineffably off about the explosion itself. Decades’ worth of viewers had no practical way to solve this maddening visual mystery, but thanks to home video, you have only to pause the film at the 31:23 mark to see exactly what’s the matter. Yes, that is indeed a ‘56 Chevy in the foreground there, together with a house and a rank of telephone poles on the far side of the explosion. I don’t know where the hell Margheriti found those few frames of something blowing up in the middle of a raggedy city street, but there’s no way he could have chosen a less appropriate bit of film to represent a crippled rocketship crashing on one of the moons of Mars! The other offers a more cerebral sort of entertainment, for it serves as the final confirmation that Ennio De Cocini has simply lost all track of what he’d written previously. It’s supposed to be a moving moment of heroism, as George’s first officer, Sullivan (Franco Fantasia, from The Giant of Marathon and The Mountain of the Cannibal God), back on Station ZX-34 goes down with the… well, I guess it isn’t a ship, really, but you know what I mean. As the A-2 approaches behind its all-destroying wall of photonic heat, Sullivan courageously mans his command post so as to coordinate the escape of as many of the crew as possible, although he himself is doomed by doing so. Here’s the thing, though… The A-2 has just passed Venus on its way around the sun, and is now entering the home stretch to Earth, right? And Station ZX-34 is in Galaxy M-12, right? So how exactly does the interstellar fireship come within 5000 miles of the station on its final approach to Earth when ZX-34 and the homeworld ought to be untold millions of light years apart?
You can easily see, then, that Assignment Outer Space is a singularly flaccid example of hard sci-fi, scarcely deserving of the earnest gravity with which Margheriti has attempted to invest it. It’s both dumb and dull on the whole, despite a few impressively forward-looking touches like treating a black man in a position of respect and authority as if that were a completely ordinary and unremarkable state of affairs. About the best thing I can say for this movie in its intended role is to note that it marked the debut of some lovely spaceship models that would become as familiar as old friends in Italian sci-fi films throughout the rest of the 60’s. Most notably, fans of the Gamma 1 series will recognize the BZ-88 as being just a paintjob away from the United Democracies Space Command flagship, and I believe Station ZX-34 enjoyed a second career as one of the Delta-series orbital bases in those movies as well. It isn’t much to go on for ordinary, non-obsessed viewers, but like I said at the beginning of the review, everybody has to start somewhere.
Home Alphabetical Index Chronological Index Contact