7 ms·
The many faces of undefined in JavaScript
- Maxion 2y agoIt never fails to amaze me how JavaScript still has so many inconsistencies and weird behavior. My biggest pet peeve is the lack of decimal in the main language.
- jimbob45 2y agoWould it really kill us to include an interpreter for literally any other language for the browser? Same for HTML. It's not just that Google owns everything browser-related in 2024, it's that the concept of an application-as-a-platform for apps doesn't need to be locked down to any one set of components like it is now.
- sophiebits 2y agoWe did! WebAssembly! Most languages aren’t infinitely backwards-compatible so unless you want to be running Python 2.7 forever or whatever…
- egeozcan 2y agoBut with WebAssembly, you need to DIY a lot and/or send a lot of runtime/stdlib code to the browser. It definitely has its place but something like Dart with excellent stdlib would be amazing (and I know that actually was the intent when Dart was being developed, I know, and I did oppose it at the time). Browsers then could ship different versions, and you can enable them, like "use strict" in js. On the other hand, I understand why not: You ship Dart and Python folk will be WTF, you ship Python and that would annoy the Java/.NET folk, and so on...
- emseetech 2y agoWebAssembly as a lower level abstraction is going to make web dev very interesting once the tech finally pays off, but it's been almost 10 years since it was announced and there's still no viable alternative to javascript to come out of it. It would have been nice if a cleaner, stricter and more "designed" alternative with full access to browser features had emerged in the meantime. I'd even accept Dart if it had managed to get broad browser support. Instead we're in a waiting game where we're all forced to use Javascript for any real work until the horizon is crossed and we can finally use a dozen of wasm-targeted languages.
- flohofwoe 2y ago> but it's been almost 10 years since it was announced and there's still no viable alternative to javascript to come out of it Are you aware if AssemblyScript? https://www.assemblyscript.org/ https://www.assemblyscript.org/ But arguably, the main purpose of WebAssembly is to use existing languages on the web, not necessarily invent new ones or even to replace Javascript.
- throwitaway1123 2y agoI've been following AssemblyScript for years but I can't recommend it until they figure out closures: https://github.com/AssemblyScript/assemblyscript/issues/798 https://github.com/AssemblyScript/assemblyscript/issues/798
- emseetech 2y agoAssemblyScript can't access the dom without interfacing with Javascript which is a major piece that needs to be solved with wasm generally. I'm arguing we should have invented a new native language to replace javascript, which could have provided a stop-gap solution until wasm targeted languages are viable.
- deleted 2y ago[deleted]
- flohofwoe 2y ago> which is a major piece that needs to be solved with wasm generally. I use WASM everyday and I don't agree that this is anywhere near the top of the things that need to be fixed. The DOM is inherently slow by design, accessing it through a JS shim or "directly" from WASM really wouldn't make any difference in performance. And on the language level, the DOM is just another web API accessed through a wrapper library like https://rustwasm.github.io/wasm-bindgen/examples/dom.html https://rustwasm.github.io/wasm-bindgen/examples/dom.html. Also the "fixed" Javascript is called Typescript (maybe combined with a very strict linter).
- baq 2y agoUntil browsers ship with a standard distribution it’s going to be a pain to download <insert my favorite language> toolchain for each site. Not that it’d help much. Browsers aren’t 100% compatible between even their own releases with the one runtime they ship.
- mjevans 2y agoI guess we could all try to write things in WebAssembly hosted forth... however that sounds like a giant nightmare once I consider any project of scale and how it would be more like trying to mod a modern JIT program at runtime with reflection. https://www.google.com/search?q=web+assembly+forth https://www.google.com/search?q=web+assembly+forth I think the parent post wanted a more easily composed, modular sources of a whole, but better than JavaScript / ECMAScript. Intended to also have something similar to modern dev consoles attached with ease.
- throwitaway1123 2y ago> Most languages aren’t infinitely backwards-compatible so unless you want to be running Python 2.7 forever or whatever… This is an important point that I think gets overlooked quite a bit in these discussions. Web tech is essentially append only — you can add things but it's incredibly difficult for a browser vendor to make a breaking change because no vendor wants to be perceived as the one that "breaks the Web". Even technologies that were never technically standardized like Web SQL end up sticking around for far too long. I'm not sure if many programming language communities would like to be constrained by this and the slow TC39 language proposal process.
- DemocracyFTW2 2y ago> Web tech is essentially append only not if you implement backwards-compatible opt-outs for which see my reply concerning pragmas a la `'use strict'`
- throwitaway1123 2y agoThis is mostly conceptual rather than technical, but I view pragmas like use strict as an append operation. If browsers dropped sloppy mode completely and made strict mode the default for all scripts, then that would be a true delete operation. I wouldn't be surprised if browsers still support sloppy mode cruft like the with operator in 2034.
- DemocracyFTW2 2y ago> I wouldn't be surprised if browsers still support sloppy mode cruft like the with operator in 2034 And may they do it, I don't care except for the weight of the little-used lines of code that are carried forward indefinitely. And it's not only 'append'; appending stuff we can without breaking backwards compatibility, it's the 'update' operations that curiously many view as infeasible despite there already being `'use strict'`.
- throwitaway1123 2y ago
- ifwinterco 2y agoI think the main issue is the DOM API is designed around JS. Running another scripting language with different semantics in the browser is trivial, having it interact with the page and do anything useful is not
- DemocracyFTW2 2y agoMy suggestion would be to add more pragmas akin to `'use strict'` to the language and it's a complete enigma to me why TC39 seemingly does not go in this general direction. Pragmas would allow to break backward compatibility, this green-eyed monster from the swamps that keeps from just doing the right thing because it would break code. I'd be fine if new syntax for that was introduced, like `%use sane`. JavaScript is too precious to be discarded. Nobody is an expert in an entirely new language, I say let's rather build on the experience of gazillions of well-informed JavaScript users and rip out the bad parts. With pragmas we can do that.
- paavohtl 2y agoThe only mainstream language I'm aware of which supports high / arbitrary precision decimal numbers as a language feature is C#. Java, Python and Ruby have them as libraries included with the standard distribution, but to my knowledge they don't have any capabilities you couldn't implement yourself in a library. Regardless, there is an active proposal to add a 128-bit decimal type to JS: https://github.com/tc39/proposal-decimal https://github.com/tc39/proposal-decimal
- medv 2y agoJs has n sufix: 1234n
- nanofus 2y agoThis was a nice read, well-written and informative! I could add that in my mental model, the reason that an object property with an undefined value is different from an actually undefined property, is that since JS objects are basically key/value maps, there is a difference between a key existing with an undefined value and the key itself not existing at all.
- langcss 2y agoThe Json serialisation and serialisation of undefined fields is a bug then? Since it changes the meaning.
- the_gipsy 2y agoNo. JSON is a subset of JavaScript.
- mirekrusin 2y agoJson doesn’t have notion of undefined value anywhere, only null and absence can be encoded.
- afiori 2y agoAlso if missing and undefined where the same it would change how prototype inheritance worked (maybe for the better)
- deleted 2y ago[deleted]
- tipiirai 2y agoFor me, the flexibility that comes from loose typing is one of the biggest strengths in JavaScript. For example, using loose equality (double equals) is truthful for both null and undefined, but false for 0.
- throwaway0665 2y agoI consider loose equality to be a bug not a feature. It's nice that `undefined != null` is true but to me it's a "trick" and not something that I want to see used all that often. It's really not that much extra to do `x !== undefined && x !== null` and keep the code intuitive.
- afiori 2y agoAs long as you are comparing with a literal then == with nulls is very intuitive. I agree that if it did not exist it would be not worth to be added and that almost every other use is bad, but != null and == null are very easy to learn idioms.
- 8n4vidtmkvmk 2y agoThis is handy, and I take advantage of it all the time. Not sure I'd call it a strength so much as a shortcut so that the botchery isn't as painful.
- jamil7 2y agoThis might be useful in limited situations in which you don't control something you're interaction with, but otherwise it seems like a codesmell.
- boredtofears 2y agowhich is exactly why you normally don't use double equals
- brabel 2y agoI like how Groovy defines truth. Anything that is not one of these is true: * 0 * null * false * empty String/collection It may seem like too many rules, but it's very intuitive. For example, it's common in Java to do: if (str != null && str.length > 0) Or: if (str != null && !str.isEmpty()) There's even a apache.commons helper function for that: if (!StringUtils.isNullOrEmpty(str)) While in Groovy that's just: if (str) It's just handy. It also reminds me of Common Lisp, where `false` is defined to be the empty list itself! It just makes sense and in Common Lisp code the same idiom can thus be used, which makes it very easy to read and write.
- aantthony 2y agoThere is also one more kind of undefined, which is undefined as a type: the string value "undefined" for `typeof undefined`
- spoiler 2y agoThe TypeScript portion is a little bit wrong. Return position void in TypeScript means the value is unobserved by the caller, not that it's undefined. It's subtly different.
- langcss 2y agoTypescript also differentiates between checking and compiling as two different steps. So you could return something from a void function and use it and that will compile to JS and work but only the compile time type check would fail. Highlighting that of course TS has no runtime checks of types.
- spoiler 2y agoYes, that's true of TypeScript in general. Code that fails type checking still gets emitted as JS. It's a bit annoying, but there's good reason for it. However, it can be controlled with compilerOptions.noEmitOnError (can be passed as a flag too). https://www.typescriptlang.org/tsconfig/#noEmitOnError https://www.typescriptlang.org/tsconfig/#noEmitOnError That being said, if using something like SWC or wrappers that's less useful, since they don't type check. TypeScript is great, but setting up projects that use it often come with some tradeoff (but I still think TS is worth it)
- the_gipsy 2y agoJavaScript, where "Null: the billion dollar mistake" is doubled by having yet another null-ish value.
- cies 2y ago> "Null: the billion dollar mistake" That was in C, release 52 years ago. > JavaScript [...] doubled it by having yet another null-ish value. And did so 24 years later! In defense of JS they supposedly designed and implemented the language in 10 days. I find "implicit nulls" less defensible for Golang (38 years after C) and Java (23 years after C), as they had plenty of time to learn from other's mistakes.
- azornathogron 2y ago> That was in C, release 52 years ago No, it was in ALGOL W. The "billion dollar mistake" is what Tony Hoare - one of the designers of the language - called it (later on, of course).
- DemocracyFTW2 2y ago> "billion dollar mistake" is what Tony Hoare [...] called it (later on, of course) would be damning but also fun if it ever turned out they planted this as a practical joke, fully knowing what they were doing
- afiori 2y agoThe billion dollars mistake is not having nulls, you need some concept of null. The mistake was allowing nulls to be a valid value for all pointers/reference at the type level. You cannot make this mistake in an untyped language like JavaScript* The solution to this is not eliminating nulls but rather separating nullable pointers/references from non-nullable ones * Ok ironically JavaScript has an actual historical implementation bug where typeof null === "object" (basically Netscape used tagged pointers, the object tag was 0, and null was represented as a null pointer, so typeof would read the tag and return "object"
- jschrf 2y agoSimple rule of thumb: never catch yourself typing the word "undefined" in a JS/TS codebase. Easy.
- DemocracyFTW2 2y ago¥€$
- bogdan 2y ago> void doesn’t introduce any new semantics to the language. I'm sure the author is most likely aware of this plus the context is around TypeScript but I think it can still be misunderstood and if you haven't been around when IIFE were very common you might not be aware that: `void` is a javascript operator and it does have semantic meaning, it evaluates an expression and returns undefined. const a = void 1; console.log(a); // undefined see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/void https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
- teamonkey 2y agoIs there any reason you’d want to do this?
- winrid 2y agosaves a couple bytes if you're not using a modern build system :)
- leosanchez 2y agoI think minifiers use 'void 0' instead of undefined.
- pintxo 2y agoExecuting something with side-effects when you don’t care for the return value?
- kaon_ 2y agoOne positive note: I think the name "undefined" is actually very fitting for what it represents.
- DemocracyFTW2 2y agoThe thing is though that `{ a: 1, d: undefined, }` and `{ a: 1, }` make a difference that shouldn't be there at all, and in this case its name is not very fitting as it does define an property of the object. This can be extremely annoying and the only way out is to always have tests around `null`, `undefined` and missing keys and have coding standards like I for one never use `undefined` explicitly; whenever it does occur it's likely a mistake; even functions without return value I make return `null` ("see, I have nothing to say here") explicitly instead of relying on the implicit `undefined`.
- ivanb 2y agoThis was probably the single worst design decision of JavaScript. It is the only language I know of that has two "absent value" types. If null was a billion dollar mistake, then undefined adds an order of magnitude to the problem. There is absolutely no reason for undefined to exist. We've generally adopted strict mode. I think it is now time to come up with and adopt a new no-undefined mode. And yes, it should break the standard library. It is worth it.
- afiori 2y agoIn almost every case you test for someVal != null or someVal == null (which is almost the only case where == is preferable to ===) And on the other hand sql made the opposite mistake where NULL means both "this field has an empty value" and "this field does not have a value"
- dwb 2y agoVBScript wants a word: https://ericlippert.com/2003/09/30/a-whole-lot-of-nothing/ https://ericlippert.com/2003/09/30/a-whole-lot-of-nothing/
- eaglelizard 2y agotypeof null === 'object' // true Brendan Eich has elaborated on why the decision was made, whether it was a good one or not - null is an empty object pointer. Idiomatically, I'd argue that `null` shouldn't exist in Javascript, since undefined is the global "default empty" value.
- chilling 2y agoWell, well, well... Not so long ago, I joined the opposing camp where everyone was arguing to drop null into the Mountain of Doom. https://medium.com/@hbarcelos/why-i-banned-null-from-my-js-code-and-why-you-should-too-13df90323cfa https://medium.com/@hbarcelos/why-i-banned-null-from-my-js-c...
- lifthrasiir 2y ago> It is the only language I know of that has two "absent value" types. It's not very common but not unique either. Perl has `undef` that roughly works identically, which became generalized into the "undefinedness" concept in Raku [1]. Ruby doesn't have `undef` value, but it could have been in the alternative universe [2]. Even more languages have multiple absent values which are not necessarily compatible to the null-undef distinction (e.g. Objective-C). --- I think the separate `undef` value was mainly regarded as a solution to the apparent problem of detecting the absence in general, for example the absence of index or argument. Consider the following Python program for example: def foo(obj=None): ... It is clear that the optional `obj` argument cannot alone distinguish `foo(obj=None)` from `foo()`. A common idiom is to have a private object in place of `None`: _NOT_GIVEN = object() def foo(obj=_NOT_GIVEN): ... It is still possible to somehow obtain a reference to `_NOT_GIVEN` and therefore use `foo(obj=_NOT_GIVEN)` which is indistinguishable from `foo()`, but why would you do that? `None` is sometimes a valid argument to the optional argument, but `_NOT_GIVEN` is clearly designated to be invalid for that. Now rename `_NOT_GIVEN` and make it a language construct---voila, you've got `undef`. `Undef` might have been a working solution a decade ago, when we were still struggling with dynamically typed languages in general and systematic approaches were less common. Lua for example uses `nil` for both purposes; `t[key] = nil` is a valid way to remove given key from the table `t` (with a caveat that it doesn't shift any subsequent keys if the key was an integer) and an excess argument is filled with `nil` [3]. This is painful from time to time, say, a table of optional integers is not straightforward. `Undef` might have been a good compromise under this observation... if we didn't have any algebraic/sum data type like today. [1] https://docs.raku.org/language/typesystem#Undefinedness https://docs.raku.org/language/typesystem#Undefinedness [2] https://stackoverflow.com/questions/6975266/what-is-the-undef-object-of-ruby/6982196#6982196 https://stackoverflow.com/questions/6975266/what-is-the-unde... [3] Lua even tried hard to remove any visible distinction between the actual `nil` and real absence of value! But it's still not perfect, and the discrepancy is much easier to detect from the C API.
- kennu 2y agoI never use null in Javascript, because I don't want attributes of type null, I just want attributes to either be present or not. This usually simplifies all designs and there is no need to think about null separately; it's treated in code an invalid value for an attribute. The remaining caveat is that when serializing an object, attributes of type undefined need to be skipped, and some libraries get that wrong. So sometimes it is necessary to delete them from objects before serialization. So in my view, things would be better if null didn't exist at all and if assigning an undefined value to an object attribute would actually delete the attribute from the object. Of course the language can't be changed now, but that is the philosophy I try to use in code design. I do realize there is the use case of passing an update object e.g. with HTTP PUT/PATCH and wanting to make a distinction between "don't update an attribute" and "remove an attribute". In that case, null kind of makes sense as a designator to remove an attribute.
- Vanit 2y agoNull is the sole case in js that should always be == checked. Null or undefined should never be === unless you're explicitly encoding a semantic difference in your types.