9 ms·
In JS functions, the ‘last’ return wins
- the_gipsy 5y agoWhy can’t they get straight to the point?
- jaffathecake 5y agoYou'd be surprised how many people don't know about 'finally' at all. Given how many of JS APIs are async, there hasn't been much call for 'finally', so folks haven't encountered it. I think they're useful again with async functions, which is why I documented that. You might be _very smart_ and know that stuff already, but the article wasn't written specifically for you. Having worked at the BBC, I'm a fan of the Reithian principles; Educate, entertain, and inform. Yes, there's a central point to the article, but I like using that as a starting point to look at related things, like async functions, and the promise stuff. TL;DR: It's an article, not a tweet :)
- ludamad 5y agoJust as another assurance, the article was not hard to skim for the main point
- cmrdporcupine 5y ago> Please never quiz folks about this in a job interview. And yet, you know someone will and they'll feel very clever for it.
- swagasaurus-rex 5y agoOn a whiteboard
- ludamad 5y ago"Please never quiz folks about this in a job interview." I have seen these types of 'well if they get this it's a good sign' type of questions. I guess if you really want that you could ask "What is a little known feature in a language you know well?"
- woutr_be 5y agoA better question would be, especially for JavaScript; “what are the bad parts about JavaScript?”. A person with actual real life experience will at least be able to list a couple.
- wizzwizz4 5y agoI think a better question would be "what are the good parts about JavaScript". Everyone knows the bad parts (right?).
- woutr_be 5y agoPeople know what they like about it (the good parts), it takes a more experienced person to be able to explain what they dont like.
- rgoulter 5y agoAs always, I think discussion really helps back it up. But I'd expect someone who has had experience with some language/library/framework will have run into problems with it, and so will be able to discuss some problem which hints at that experience.
- wizzwizz4 5y agoFor most things, yes. But this is JavaScript, the language where intransitive equality, implicit object-to-primitive casting and mutable global objects must be used in all slight-above-trivial code. Where `typeof` is useless and wrong, but nonetheless necessary; where there are seven different ways to parse a number, with six different semantics… there's a reason that “JavaScript: The Good Parts” is such a short book. https://blog.klipse.tech/assets/js_good_parts.jpg https://blog.klipse.tech/assets/js_good_parts.jpg Somebody who knows the good parts of JavaScript is a JavaScript expert. You want somebody who can write good JavaScript, and using the bad parts well has nothing on using the good parts adequately.
- 5y ago
- TrowthePlow 5y agoThis seems much less about which return actually 'sends data back' (terminates function execution) and more about how try/finally works in general
- lucideer 5y ago> The same happens in Java and Python too. And yet, I expect this will soon appear in those "JS is weird, wtf" listicles.
- whoisthemachine 5y agoC# does not allow returns from a `finally` block, which has annoyed me at times. However, seeing the consequences of allowing the behavior realized in this article, I am happy for the rule.
- masklinn 5y ago> C# does not allow returns from a `finally` block I think C# does not allow any flow control in finally blocks, so no continue or break either (well for continue and break they're allowed if the statement they "refer to" is also in the finally block, but flow control can't go through or escape from the block). Essentially in C# a finally block can only be escaped from by falling off of the block's end.
- karldcampbell 5y agoDoesn't javac issue a warning for this? I know most IDEs do.
- cousin_it 5y agoReminds me of the unescapable loop: while (true) { try { return; } finally { continue; } }
- moritzwarhier 5y agoNice. :) Looks like a good minimum example to show that the intuitive natural language semantics of try and finally don't work with statements like continue that change control flow.
- paulddraper 5y agoIt works how is i'd expect.
- chrisseaton 5y ago> a good minimum example to show that the intuitive natural language semantics of try and finally don't work with statements like continue I try returning but finally it continues the loop. Literally reads as written?
- edflsafoiewq 5y agoreturn x can be understood as ret = x; // assign to the implicit return variable return; // return ret to the caller If the return is cancelled by a finally, its basically just the case of assigning to the ret variable multiple times; the last assignment wins. There are a few languages where functions have an actual ret variable you can explicitly use.
- jaffathecake 5y agoIt's more of a 'result' variable, because the result can be a return or a throw. If you throw, it clears the return, and vice versa. I had something like this in the article originally, but then you also need to say that `catch` also does `_result = undefined`, and it felt messy.
- dvt 5y agoThis article omits getting into try-catch-finally semantics, and it's not really that mysterious when you think about it (although, yes, please don't ask people about this in an interview): - A catch block is only executed if an exception is thrown in the try block. - A finally block is executed always after a try(-catch) block, if an exception is thrown or not. > As a side-effect, returning from finally clears a thrown error: Exceptions aren't "cleared," they are "finally-d." Because that's how finally works[2]. The final block, if evaluated, always overrides the result of the previous blocks. A slightly more interesting example of try-catch weirdness is how catch blocks are one of the few constructs that create new scope (technically augment scope): function F() { try { throw "error"; } catch (err) { err = { "hello": "world" } var hoisted = "foo" console.log(err) } finally { return hoisted; // works, since this gets hoisted to the top of F return err; // breaks, since err is spooky and only "scoped" in the catch block } } [2] https://tc39.es/ecma262/multipage/ecmascript-language-statements-and-declarations.html#sec-try-statement https://tc39.es/ecma262/multipage/ecmascript-language-statem...
- jaffathecake 5y agoThe way I think about it: `return` and `throw` set the function's result. `catch` automatically unsets the function's result. How `finally` works can be explained from that.
- dnautics 5y agoIt's akin to how in pascal you set the return value by assigning the name of function. I think. It's been decades
- thijsvandien 5y agoOr the variable `Result` (most common nowadays), although you may also call `Exit()` with a parameter.
- jonny_eh 5y ago
- bobbylarrybobby 5y agoReminds me of VBA, where the way to “return” a value in a function is to assign it to the function’s name Sub f() 'returns 1 f = 1 End I always thought this was insane, but it does make the semantics clear. Maybe not so insane after all
- TheSoftwareGuy 5y agoFORTRAN does the same actually
- masswerk 5y agoThis makes a point for separating the semantics of (a) control flow (a premature exit, similar to break in a loop) and (b) assigning return values. However, JavaScript actually started with rather quirky semantics for return: if any exit returned a value, all exits had to return a value, otherwise an error was thrown. Yet another effect of the nexus of control flow and assignment of a return value. (This got fixed with the introduction of the return object as workaround, which was, I think, in ECMA-Script 3.)
- Smaug123 5y agoF# lacks an imperative "return" at all - a function returns precisely the value of the expression that is its body - which makes it a lot easier to think about this kind of thing, at the cost of sometimes having to be explicit about assigning a value to the result of a `try/with`.
- voidnullnil 5y agoBlogs about "return" inside "finally" in Java and the likes were common in the 2000s. The fact that languages have so many simple things like this that surprise people indicates that there is a problem somewhere. I'm sure some of the older school languages (like VB maybe) had some insane semantics like an interrupted return will return null, I can't remember them in that much detail.
- deleted 5y ago[deleted]
- ajkdhcb2 5y agoI finished reading this and felt that it was annoying clickbait. The example it started with (that I saw in a preview before clicking) was just misleading
- byteface 5y agoI found finally is useful for kicking off a job after returning a response within the same func without having to spawn another process or block. i.e. return a 200 response immediately in the catch then kick your slow running job off in the finally. They can poll back for results when baked.
- locallost 5y agoI doubt I know a single person that knows this (me included, until now at least). Fortunately I've never seen this actually being used. It's a bit troubling that the promise version behaves differently because most people view try/catch to be generally equivalent to the code that uses promises. I'm making a note to link to this article the first time I see it in a PR :-).
- jonny_eh 5y agook, so what does this print? try { return console.log('one'); } catch(err) { return console.log('two'); } finally { return console.log('three'); } Tip: The results are "odd".
- re 5y agoNot sure I'm call them odd -- it prints the same thing that would be printed without the "returns" (i.e., if the blocks contained only console.log calls), which is what I'd expect it to print: 'one' followed by 'three'. You're maybe thrown off because, while only one return statement can successfully return a value from the function, more than one can be executed, with their values evaluated.
- jonny_eh 5y ago> 'one' followed by 'three' Right! Those are the "odd" numbers! ;)
- valbaca 5y agoUncaught SyntaxError: Illegal return statement You're trying to return the result of console.log, which is undefined, which you cannot return explicitly
- Twixes 5y agoYou very much can return `undefined`, it's just that `return` only works inside of a function, not if you just copy the block of code into the console :)
- edflsafoiewq 5y agoWhat's "odd" about it? It does exactly what I'd expect.
- HJain13 5y agoOne and three are "odd" numbers
- valbaca 5y agolow effort article explaining precisely what `finally` does in JS that is in no way surprising
- natenthe 5y agoThis reminds me of something that would be included in a JS engineering interview. I find questions like this to be ridiculous. Knowing the answer to a question about this 'gotcha' would be a pretty terrible signal about future engineering performance. I'll focus on writing good software and solving complex problems, thanks. After reading this article, I feel slight annoyance. But maybe that is just me.
- SavantIdiot 5y ago> I hadn't used finally much in JavaScript until recently, where I find myself using it like this in async functions: We can tell by your notation. Mixing try blocks with async/await and promises is mixing patterns and obscuring what you are attempting to accomplish.
- jaffathecake 5y agoNope. It was designed precisely for patterns like this.
- SavantIdiot 5y agoReally? I don't follow: why is try/catch/finally preferred over: async function someAsyncThing() { startSpinner(); await asyncWork() .catch(err => { if (err.name == 'AbortError') return; showErrorUI(); }) .finally(() => { stopSpinner(); }); } Should be identical, no? EDIT: Well, except that if there was more after asyncWork() the return in the try block would exit someAsyncThing, whereas the return in the catch block just returns from the catch. Is that his point?