I used to hate being forced to use them, just because as a recent computer science graduate I was happy with nested conditionals everywhere. But guard clauses make life so much easier, I eventually discovered.
They make testing your code a lot easier, and also make reasoning about the code and reading it so much easier.
Ruby makes writing methods with guard clauses a breeze, since you can just write something like `return if x > 7`.
Are there any preprocessors or libraries to make statements like this easier in Javascript? Sometimes the guard statements can be longer than the function code and I go back and forth on whether to throw (forces the caller to anticipate) or return (causes lots of silent failures).
It would be great to use a defined approach.
I work in Python, and one thing I do if I end up needing to use the same guard clause in several functions is to turn it into a decorator. That way, if I need to update the logic, I can do it in one place and have it propagate everywhere and it makes the function's dependencies clear at first glance.
This was my introduction to aspect-oriented programming, which I've thoroughly fallen in love with.
e.g.
const check(cond) => cond && otherValue
If `cond` is falsey, it returns `cond`.This means the function could return any of: `false`, `undefined`, `null`, '', `0` or `NaN`.
This is a fairly common issue I see with React + JSX:
<div>{cond && <SomeComponent />}</div>
If `cond` is `false`, `null`, `undefined` or '', everything will be just fine, but if `cond` happens to be a zero or `NaN`, suddenly you have a weird `0` or `NaN` rendering in your page. Oops.Low cost, much safer guard:
const check(cond) => !!cond && otherValueSame behavior on Ruby:
def content_markup(children)
case children
when String, Numeric
children
when NilClass, TrueClass, FalseClass
return
else
# ...
end
end
content_markup 'foo'
#=> "foo"
content_markup 0
#=> 0
content_markup true
#=> nil
content_markup false
#=> nil
content_markup nil
#=> nilThat's the problem with antipatterns. It's impossible to remain alert to the edge cases, and then they eventually bite you in production. Better to lint them away. But it's difficult to convince people not to do something really convenient if they haven't gotten bitten yet.
cond? && otherValueIf you start thinking it is a "guard operator", I would think that going down the wrong path, which might promote misunderstanding of the behavior.
This isn't a misunderstanding, binary logical operators in JS short-circuit like this by design. I believe && and || returned a boolean value in the past, but were explicitly changed to support this behaviour.
The production LogicalANDExpression : LogicalANDExpression && BitwiseORExpression is evaluated as follows:
1. Evaluate LogicalANDExpression.
2. Call GetValue(Result(1)).
3. Call ToBoolean(Result(2)).
4. If Result(3) is false, return Result(2).
5. Evaluate BitwiseORExpression.
6. Call GetValue((Result(5)).
7. Return Result(6).
That is, the behavior has always been "If the first expression is false-ish, return the first expression, otherwise return the second expression" ("BitwiseORExpression" is a class of expressions that include a lot of things, including equality operators).JavaScript does not have any operators that is not explicitly listed in a version of ECMA-262. It would be correct to refer to the construct as a "guard", but incorrect to refer to it as a "guard operator". Calling it "guard operator" also does not promote an understanding of the underlying construct.
1: https://www.ecma-international.org/publications/files/ECMA-S...
The ECMA spec only defines Javascript 1.3 and above. See this description for logical operators for Javascript 1.1: https://web.archive.org/web/20060318153542/wp.netscape.com/e...
Doing some research, it appears that Netscape changed the logical operator behavior in version 1.2 (https://web.archive.org/web/19981202065738if_/http://develop...).
However, they did not highlight this change at all (https://web.archive.org/web/19970630092641fw_/http://develop...), so I suspect it was just a minor cleanup, potentially related to the equality operator change.
As a side-note: Netscape scripting was awful. This was how you casted an object to a Number:
Number(x) = x;This article also discusses the solutions (there's a lot of overlap with OP's article).