A thread recently arose on the es-discuss mailing list1 regarding the idea of adding an 'existential operator'2 to JavaScript. This was in line with some thinking I'd been doing lately, but which I was uanble to fully formulate to bring into the discussion on that thread, and now that the thread has been dead for a while, I'm choosing to use this forum to put down my thoughts before I decide to either start a new thread or raise the old one.
The argument for an 'existential' operator is an interesting one, with the initial poster, Dmitry Soshnikov proposing the following:
street = user.address?.street // equivalent to: street = (typeof user.address != "undefined" && user.address != null) ? user.address.street : undefined;
An interesting proposal, and functionally similar to my considerations to proposing void-safety into the language. Let's first define what I mean by, 'void-safety', a term I first read during the interview with the creator of Eiffel3 in Masterminds of Programming4. To be void-safe, a simple rule would be added to the language that any attempt to access a property on an undefined value would itself equal undefined. In other words, it would be like the above example, but it would not have the '?' character, and it would apply to all accesses of any value.
I oppose Dmitry's suggestion to address this issue through syntax, as I think that such an addition would have a lot more value being a fundemental change to the language, than an optional change requiring a potentially obscure bit of syntax. Plus, this proposal is derived directly from Coffeescript5, which is a cool language, but was designed to translate directly into JavaScript, meaning that it's solutions need to work with JavaScripts limitations in how it solves problems.
Either of these solutions helps to break a common pattern of data access, especially prevalent with configuration objects. However, there is at least one question that I've raised in my own head that has led to a bit of reluctance to post this to es-discuss. Imagine the following, fairly common pattern:
function action(config) { config || config = {}; config.option || config.option = "default"; ... Do Something ... };
With void-safe JavaScript, you could do to check for existence on config.option without raising a TypeError, however, the assignment would proceed to raise a TypeError because config is not a value which can have a property added to it. In essence, this requires the first line, resulting in no win for providing void-safety. But then, existential operator isn't really useful in this case either.
It is an interesting idea to be able to say that 'if config doesn't exist, create it and then append the option property to it, but that has the potential to create brittle code by accidentally initializing values as objects that should have been created as functions (and then had properties set) or other imaginable bad side-effects. And while it may be nice to consider functionality like the Namespace function within YUI, such a thing should always be opt-in.
There is one place where the existensial operator requests functionality that I'm not sure I'd want to see in void-safe JavaScript, and that is around functions. When applied to a funciton call, the existential operator will not call the function and just proceed past it in the property chain (potentially raising a TypeError later).
At first, I felt that applying void-safety to functions was a bad idea, one likely to cause brittleness in programs. To some extent, I still feel that way, as JavaScript functions are allowed to have side effects. The question then because is it better to raise a ReferenceError by trying to execute undefined, stopping script execution, or to continue on having essentially completed a no-op? Plus, with JavaScript's varaiable inference, where a typo can result in a new variable, there are times you'd want to have that TypeError raised, espeically during debugging.
Of course, the varibale creation by inference is disabled in strict mode, and several of these potential threats are caught by tools such as JSLint6, which can be more easily intergrated into your work process today than ever before.
The concern for me, therefore, is that the behaviour I want in development will not necessarily be the behaviour I want in production. Where void-safety comes in the most useful is likely in the processing of a JS object pulled in from an external source, be that a web service, iframe, or WebWorker, where the simplified data access with increased safety is potentially very useful.
I seem to remember seeing Brendan Eich and the Mozilla team (I'm not sure how involved the rest of the EcmaScript community is yet) discussing a new 'debugging' namespace for JavaScript, though I'm having trouble finding the source. I think the void-safety could be a good flag in this environment. By default, turn void-safety on. It makes scripts safer as the browser won't abort script execution as frequently. But developers could turn it off for their browser, allowing them more powerful debugging.
I'm still on the fence about this proposal. It can make data lookups simpler and safer, without adding new syntax, which is a win. But there are definitely circumstances where it can potentially hide bugs, thus making a developer's life more difficult if it can't be disabled. I do think I will raise the issue on es-discuss, as I think it at least warrants discussion by that community, and it may be that there are good historical reasons to not change this behaviour that others who have been buried in these problems longer than I will be familiar with.
References: