9 ms·
Don't use || to set default values in JavaScript
- vilmosi 11y ago>>> First of all, it isn’t obvious why the OR operator would be used to assign default values. Really?! This is common knowledge for anyone writing JS for more than a week. It's used EVERYWHERE.
- hobozilla 11y ago"The OR adds mental overhead for whoever works on the function in the future" What world is this guy living in? It's like it's the first time he's seen this and just decided "I don't like it, let me write an article about that". Anyone working in JS for more than a month will have seen this as common practice. It much neater (and less mental headspace IMHO) than an extra if block. Particularly if you have more than one optional variable. The only practical consideration raised is the falsy types can trip you up but that is easily negated. I have strong negative feelings for people who impose their own personal believes based on nothing but their feelings.
- honest_joe 11y agoIt might be ugly but there are more uglier things in JS :P..callbacks and so on. The way he wants to solve it however uglier imho
- merb 11y agoWhy are Callbacks ugly? I mean that's one of the best things.
- honest_joe 11y agoWell both things are subjectively "ugly". Functionally they are awesome.
- merb 11y agoI think most people still like callbacks, cause of their functional behavior. Currently more and more people are loving some functional language designs. Especially things like map() which always has some kind of inner function in every functional or 'kind of' functional language.
- jbeja 11y agoThey are not ugly, nested callbacks are ugly, and they are not ideal to deal with asynchronous code.
- pweissbrod 11y agoAgreed. His statement is based on opinion, nothing objective. I could argue that in languages like C# the coalesce operator '??' has a similar meaning, so it is intuitive for people who know C# concepts.
- MichaelGG 11y agoC#'s coalese only works on null. The problem is that JS will apparently see an empty string or 0, and consider that null. So if your function passes those values deliberately, the || trick breaks. So long you're OK with that, it seems like a clean solution. It's JavaScript. There's tons of dumb stuff a JS coder must learn. If he's confused by || then he's likely to be unable to work on any real JS.
- ericcholis 11y agoIf || is too ugly use the ternary operator, it's inline and only slightly more verbose. That being said, I think using || is a nice pattern for readability.
- zaf 11y ago> The only practical consideration raised is the falsy types can trip you up but that is easily negated. You mean adding an if block to check for the zero and blank string?
- mattmanser 11y agofruit = fruit === "" ? "" : fruit || "strawberry"; Woohoo! Javascript rocks! Note that fruit = fruit == "" ? "" : fruit || "strawberry"; May or may not be bugged depending on your understanding of a bug and whether you're a marmite fan.
- tracker1 11y agofruit = fruit === "" && "" || fruit || "strawberrry"; It's flexible too.. though imo your ternary operation is more obvious. ;-) Personally, I find that once you understand JavaScript, the beauty in what you can do, especially for input validation (which is an ugly, ugly thing) works so well in this language.
- zaf 11y agoAnd what about the check for 0? Or does the empty string handle that case as well?
- deleted 11y ago[deleted]
- Mithaldu 11y agoPerl solved that issue by introducing the // and //= operators, which do the same thing as || and ||=, but restricted to consider only undef as false.
- J_Darnley 11y agoYou mean those are not integer divide operators?
- Mithaldu 11y agoNumbers are float by default in Perl. If you want Integer operations you need to cast with int() or use https://metacpan.org/pod/integer https://metacpan.org/pod/integer
- Flimm 11y agoIt's called "defined-or" if you want to search for its documentation. I really miss it in other languages.
- kevincennis 11y agoI agree that default parameters will be a much nicer solution to this problem, but using the OR operator is a very common practice in JS, and any dev with more than about 5 weeks experience will recognize and understand that pattern pretty much automatically. In the example with the undefined check... what if undefined is a valid argument? You should actually check the length of the arguments object. See, you can always find examples of when you shouldn't do something. That doesn't mean you shouldn't EVER do it. At the end of the day, people who read and write code need to understand how it works. You can only protect people from themselves so much.
- ricklancee 11y agoShouldn't the undefined check be like this? if (typeof fruit === "undefined") { fruit = "strawberry"; } Unless your doing something like: (function(undefined) { })();
- kevincennis 11y agoIn ES5+, the global `undefined` is immutable, so it should be pretty safe unless someone declared a local `undefined` var in an outer scope.
- arnehormann 11y agoI use "var undef;" at the top of a function and never set it to a value. Comparison with === is the same as with undefined. And it's nice for minification.
- masklinn 11y ago`typeof` is useful when the binding may or may not exist at all, this is almost exclusively an issue with global variables which may not be there (toplevel APIs or libraries missing). If the binding exists at all, you can just check for its value. And parameters always create a binding pretty much by definition. So no, there is no reason to use `typeof` to check whether a parameter is `undefined`. If you fear that somebody rebound the global `undefined` for some insane reason, you can use `void 0` instead.
- CmonDev 11y agoDoesn't it also check for null not just undefined? Isn't that the whole point?
- tracker1 11y agoAny truthy value will be returned and short out the boolean expression.. falsy values fall through... falsy values are: "", 0, null, undefined, NaN and false Everything else is truthy. I kind of wish that Invalid Date (invalidDt.valueOf() === NaN), empty arrays, and objects without any properties were also falsy sometimes. Though I also wish that sometimes 0 was easier to separate from other falsy values.
- deckar01 11y agoI was always instructed to use typeof when determining if a variable or property is undefined. Some attempts to access an undefined variable will result in an exception being thrown. http://stackoverflow.com/questions/27509/detecting-an-undefined-object-property http://stackoverflow.com/questions/27509/detecting-an-undefi...
- masklinn 11y agoThat's only a serious issue if the binding may not exist at all, which is an other way to say that it's only useful for global variables. A function parameter defines a binding by definition.
- deckar01 11y agoGood to know. I peeked into underscore's source to see how this type of check is handled. Aparently the issue is more complicated than I thought, because the following comparison is used: obj[key] === void 0 Are they really defending themselves against the function being rebound with undefined shadowed? http://adripofjavascript.com/blog/drips/javascripts-void-operator.html http://adripofjavascript.com/blog/drips/javascripts-void-ope...
- masklinn 11y agoYeah. It might be an issue when you're a widely used library, you might routinely encounter completely insane stuff. In a codebase you own though, I wouldn't worry about it, you can just set whoever decides rebinding undefined is funny on fire.
- bsimpson 11y agotl;dr: use Babel to get default arguments that are both more readable and more robust, along with a bunch of other JS Harmony improvements, for free.
- aikah 11y ago> tl;dr: use Babel to get default arguments that are both more readable and more robust, along with a bunch of other JS Harmony improvements, for free. You mean replace perfectly valid javascript with a complicated nodejs pipeline in order to make scripts run in the browser now? hell no.
- tracker1 11y agoI like babel for plenty of other reasons... the single biggest one is the culmination of Promise + coroutines with async/await keywords. Not to mention being able to break code into discrete modules that can be utilized without having to jump through namespace hoops or global collisions (does $ mean jQuery, Prototype, document.querySelectorAll, ...).
- bsimpson 11y agoYou can easily get Babel, proper modules, hot module replacement, and a bunch of other goodies with Webpack. I wouldn't start a new JS project without it.
- matwood 11y ago> complicated nodejs pipeline in order to make scripts run in the browser now? Huh? Babel plugs into whatever build pipeline you already have be it webpack, gulp, etc... You also get the benefits of being able to use ES6 today which has tons of great features.
- lewisl9029 11y agoWhile I appreciate simplicity as much as the next guy, using this "complicated nodejs pipeline" gives you access to a wide array of language features that can make your entire codebase simpler. I feel this is an excellent trade-off for any non-trivial project.
- rdancer 11y agoBullshit. Using foo = bar || baz is perfectly valid when used judiciously. foo = bar || baz is perfect when parsing inputs where unset is passed as "" or 0. To no great surprise, HTML forms are one such beast. The Boolean operators are simply a shorthand for if (!foo) foo = bar -- when you mean if (foo === undefined) foo = bar; then simply write that instead. At least omit the unnecessary braces and white space. Verbose code is not necessarily more readable. You may be able to code your way around a reader not comprehending JS rules regarding Boolean coercion, but those rules are based on real world inputs which often do not have a special 'undefined' value.
- tracker1 11y agoI came in here to write pretty much the same thing... the only issue for me tends to be when 0 is allowed. As an interview problem, I will ask someone to write in JavaScript a method that takes a single parameter, that will always return a number or null.. if it's a string that represents a number, convert it, otherwise it should be null. 0 always trips people up in this, or other means of coercion. Other than that one case, I find the shortcut of || to be pretty much invaluable. This is an example of something you should just learn how it works, rather then assume it's stupid or wrong because you don't know how the environment works. You should have seen how many people went up in arms at LINQ and even Lambda functions in C#. I've seen similar comments about lambda/fat-arrow functions coming into JS.
- acjohnson55 11y agoIs that a great interview question? It strikes me as the sort of thing where a positive doesn't tell you all that much additional about someone's engineering ability, nor does a negative.
- tracker1 11y agoIt isn't the only thing I judge on, but when you see a stack of resumes where people put their JavaScript knowledge as "expert" ... I expect it to be a relatively easy question. It comes down to a level of honesty, and when someone says they are an expert with a language, they better know that language pretty well. Like "what are the falsy values in JavaScript" (I usually let people get away with 3+ of them) In the browser a very primary purpose for JavaScript is input validation... this includes strings... being able to reuse a method for internal validation is useful as well. Knowing how to do something useful in a language is a perfectly fine interview question. It isn't like I'm asking people to write a bubble-sort, or how an IEEE 754 number is structured and how that relates to JS... Or how to determine the number of marbles in a given jar... or any other of other questions I've been asked in an interview. I'm asking someone to validate a simple input in one of the most widely used programming languages on the planet. Sorry to go on a rant.. but hiring is hard, and when you are looking at someone why says they have a lot of experience with the skills that you are looking for (full-stack javascript/node)... expectations shouldn't be too low. I'm more than happy to talk to people with other backgrounds and skills... I've hired plenty of newer/eager learners who don't have a lot of experience, but demonstrated the ability to work through a problem. In my mind effort/ambition/trying-stuff means more than specific experience.
- zongitsrinzler 11y agoI don't agree. Replacing all occurrences of default values that use || with a 3 rows long if case would hurt readability. There are many valid cases where the incoming parameter could be either undefined or null.
- xsace 11y agovar skill; article = skill || 'troll'
- Ensorceled 11y agoI look for more such insightful articles from http://www.codereadability.com/ http://www.codereadability.com/ in the future. /s
- nevi-me 11y agoSimilar to what everyone else is saying, I don't get the author's point. I taught myself JavaScript a few years ago, and the first time I came across that || assignment, it made sense. I think many other people would say the same.
- chrisdew 11y agovar undefined = "raspberry"; function eatFruit (fruit) { if (fruit === undefined) { fruit = "strawberry"; } ... } eatFruit("raspberry");
- robinson7d 11y agoNot that I agree with the sentiment of the article (defaulting with || is usually okay!), but hopefully people reading these pieces, and worrying about such things, are already using strict mode.
- tracker1 11y agoyou can also use... if (foo === void 0) ... //or var undef; ... if (foo === undef) ...
- kcorbitt 11y agoI was intrigued and just tried this. It doesn't work (at least in the chrome console) -- "undefined" is a reserved keyword and while the interpreter doesn't complain about attempting to assign it the value of "raspberry," it appears to ignore the statement.
- smhg 11y agoI don't agree either. The first part of the argumentation is indeed based on the author's feelings. The second part I don't think is an issue for most real world use-cases (Objects, Strings and, to a lesser extent, Numbers). On the underscore (_.defaults) recommendation: let's set our goals straight [1]. Aim for a good level of JavaScript understanding. Instead of library knowledge to make up for the lack of the former. [1] https://www.youtube.com/watch?v=4anAwXYqLG8 https://www.youtube.com/watch?v=4anAwXYqLG8
- PythonicAlpha 11y agoIt is similar as in C: When C come out, it did not include a bool type, since it could be easily implemented as integer or char. The result was, that every bigger project had its own standard of the boolean type. This lead to the situation that bringing together different libraries or projects in the same company, you very soon had four or more different (and potential incompatible) boolean types with different constants for TRUE, FALSE, true, false and UNDEFINED. The programmers where happy to deal with those ... It would be best (and fastest) to include something like default parameters into the language much sooner ... But at least in this case, I see much less trouble as with the C type and I do not agree with the author that there is mental overhead involved with the OR operator, since you normally get used to it fast.
- domainkiller 11y agofruit = (fruit === undefined) ? "strawberry" : fruit
- mromanuk 11y agoThanks, but no. I will use ||