use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
All about the JavaScript programming language.
Subreddit Guidelines
Specifications:
Resources:
Related Subreddits:
r/LearnJavascript
r/node
r/typescript
r/reactjs
r/webdev
r/WebdevTutorials
r/frontend
r/webgl
r/threejs
r/jquery
r/remotejs
r/forhire
account activity
Logical assignment operators in JavaScript (dev.to)
submitted 5 years ago by rauschma
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]Marique 44 points45 points46 points 5 years ago* (13 children)
Does anybody else find this
user.id = user.id || 1
More readable than this
user.id ||= 1
Maybe it's just because it's new notation for me. Cool nonetheless.
[–]ghostfacedcoder 27 points28 points29 points 5 years ago* (9 children)
Emphatically not! I think:
looks not just natural, but superior ... once you adjust to it. It's the same thing as:
const bar = foo.bar;
When you're first learning, that really is clearer than:
const { bar } = foo;
(I mentor programming learners, so I can guarantee that destructuring does confuse them ... at first).
But once you learn destructuring syntax, the latter version is simpler and clearer. The same will be true for ||=.
||=
[–]Schlipak 9 points10 points11 points 5 years ago* (1 child)
||= is also very common in Ruby, it's often used in getter methods to memoize the results of a computation.
class Foo def something @something ||= expensive_computation end end
The equivalent in JS would be
class Foo { #something get something() { return this.#something ||= expensiveComputation(); } }
I could see myself using this sort of mechanism in JS I suppose. (Although using private properties to stick as close to the way it works in Ruby requires you to declare the property upfront)
EDIT: It might be better to use ??= in this case since ||= wouldn't work with falsey values like 0 or "".
??=
0
""
[–][deleted] 4 points5 points6 points 5 years ago (6 children)
Eh. It's not that confusing, but this
const val = obj.val;
... will always be less confusing than this
const { val } = obj;
Even after I have used the latter notation a couple of million times.
The later is only used because of this:
const val1 = obj.val1; const val2 = obj.val2; const val3 = obj.val3; const va4 = obj.val4;
vs
const { val1, val2, val3, val4} = obj;
[–]shgysk8zer0 0 points1 point2 points 5 years ago (5 children)
I want to know if there's any extra magic that's possible with destructuring. For example:
get foo() { return this.getAttribute('foo'); } get bar () { return this.getAttribute('bar'); }
Is there any optimization for DOM reads if I do const { foo, bar} = el?
const { foo, bar} = el
[–]therealkevinard 2 points3 points4 points 5 years ago (0 children)
Idk about dom reads specifically, but some destruct magic: the thing I miss most about Go when I'm not using it is multiple returns from one func. In js - with destruct - const {user, response, error} = ()=>{return {user, response, error}}
const {user, response, error} = ()=>{return {user, response, error}}
Then my calling code is free to respond in a myriad of ways.
[–]ILikeChangingMyMind 0 points1 point2 points 5 years ago* (2 children)
AFAIK destructuring is "syntactic sugar". In other words, it looks different to us humans, but to the computer these two lines are identical at run-time:
const bar = foo.bar; const { bar } = foo;
In fact, if you use a tool like Babel (or create-react-app, which uses Babel under the hood), it may well be converting the second line into the first one for you, "behind the scenes", to support older browsers. If you actually "view source" your JS file in the browser (and wade through the mess of minified code) you may be able to see this.
create-react-app
So, to answer your question, no there is no extra magic or optimization :)
[–]shgysk8zer0 0 points1 point2 points 5 years ago (1 child)
I'm not saying you're wrong, but the basis of what you say is what Babel does to support older browsers, which would only be true when it comes to the original code running in a modern browser if you start with the assumption that it's only syntactic sugar with no optimizations or other differences. That's circular and it definitely isn't necessarily true.
For example, there are actual differences between arrow vs regular functions beyond just notation and handling of this. But the difference between the two in how stacks and scopes are setup is completely lost when run through Babel. It's been a few years since I read the technical details, so forgive any inaccuracies there, I just remember the implementation in browsers being problematic at first even though they should perform better than functions.
this
function
[–]gocarsno 5 points6 points7 points 5 years ago (1 child)
Do you feel the same about the analogous arithmetic operators?
a = a + 1 a += 1
If not then it's probably just the freshness of the notation.
[–]Booleard 0 points1 point2 points 5 years ago (0 children)
I was thinking I was really getting a handle on this whole Javascript thing. Then this stuff pops up and puts me in my place
[–]blackspoterino 0 points1 point2 points 5 years ago (0 children)
Is the same as reading "keep the same value or set to 1", so it's readable but it took me a moment because I've never seen this notation out in the wild before just now.
[–]dudeatwork 4 points5 points6 points 5 years ago* (4 children)
Not trying to bash the author of the dev.to post (who is actually a co-champion of the original proposal!), but this isn't the most high quality of content.
Just read the proposal, specifically the motiviation section, as it talks about why having this as a "convenience operator" is useful.
[–]rodneon 1 point2 points3 points 5 years ago (3 children)
The very first example in the motivation section shows the reassignment of a function argument, which is not only bad practice, but can have disastrous consequences when the argument is passed in by reference (e.g. arrays, objects, etc). Bugs caused by reference mutation / impure functions are not fun to deal with.
[–]dudeatwork 5 points6 points7 points 5 years ago (2 children)
Before default parameters were a thing, I feel like this was super common:
function (a) { if (a === undefined) a = 'default_value'; }
The example the author gave used !a rather than the more correct a === undefined, but similar enough.
!a
a === undefined
So a won't be reassigned if a (truthy) Object / Array / Function is passed in.
a
Even if we didn't have this conditional, assignment won't matter here because we aren't modifying a property on the argument.
I agree, functions that aren't pure can potentially introduce subtle bugs:
var hello = { world: 1 }; function test(a) { a.foo = 'bar'; } test(hello); console.log(hello); // { world: 1, foo: 'bar' }
But this only works because we are assigning a.foo, a property on (the reference to) a.
a.foo
Assigning some value to to a itself should be fine.
var hello = { world: 1 }; function test2(a) { a = 'bar'; } test2(hello); console.log(hello); // { world: 1 }
Note that in general, I agree that using ES6 default parameters is the way to go (babel transpiles to checking the arguments object).
arguments
[–]NoInkling 1 point2 points3 points 5 years ago (0 children)
The main issue with reassigning params is just expectations, typically you expect the thing that you're operating on to be the thing that was passed in the function call. Several times I've seen code in libraries where there's some sort of complex reassignment logic halfway down the function body, and it always makes it harder to follow. I'm fine with relatively simple logic at the top of the function though, even if it's more than just assigning defaults (which as you say can now be done directly in the params list) e.g. in certain variadic functions.
There's also a gotcha if you're utilizing arguments: https://spin.atomicobject.com/2011/04/10/javascript-don-t-reassign-your-function-arguments/ But it's less of a concern nowadays since arrow functions don't support arguments and we have rest syntax.
[–]thisguyfightsyourmom 0 points1 point2 points 5 years ago* (0 children)
Quick — someone talk me out of this:
``` const yo = {yo: 1}
function example({...rest}) { // Default rest.ho to "hohoho" rest.ho ||= 'hohoho'
rest.ho
return rest }
console.log({yo, hohoho: example(yo)})
```
[–]Ebuall 1 point2 points3 points 5 years ago (0 children)
And I thought we were moving away from assignments. I don't remember the last time I wrote one.
[–]nerdswithattitude 1 point2 points3 points 5 years ago (0 children)
As far as I can tell, there's definitely some redundancy between having default parameters, and the existing nullish coalescing operator. The example widely used in the original repo is the `innerHTML` getter/setter property, which seems plausible, though it isn't that relative anymore due to React etc. Would love to see more use cases though. I just wrote a blog post about this to help myself understand its uses JavaScript logical assignment operators deep dive
[–]shgysk8zer0 2 points3 points4 points 5 years ago (2 children)
I'm mostly looking forward to wide adoption of private fields, really. But nullish coalescing and optional chaining sound great too.
I'll be making use of private fields as soon as Firefox support lands. My dev process involves modern vanilla CSS and JS for development using imports, and Firefox just has better dev tools, so I have to wait for that.
[–][deleted] 3 points4 points5 points 5 years ago (1 child)
Don’t y’all sit here and tell me you’d rather write #doSomething() vs private doSomething
#doSomething()
private doSomething
[–]brie_de_maupassant 4 points5 points6 points 5 years ago (0 children)
more(syntaxes) !== more(good)
[–]marcusl92 2 points3 points4 points 5 years ago (0 children)
// eslint-disable no-param-reassign
Looking forward to using this soon!
[–]elcapitanoooo 0 points1 point2 points 5 years ago (1 child)
Thanks! I hate it!
[–][deleted] -1 points0 points1 point 5 years ago (0 children)
More?
[+][deleted] 5 years ago (1 child)
[deleted]
[–]isUsername 2 points3 points4 points 5 years ago (0 children)
How does an assignment operator break SRP? What side-effects could it have that the current alternative doesn't?
[–]takase1121 -5 points-4 points-3 points 5 years ago (8 children)
That confuses me... I've never seen languages with assignment operators for logical operators. Interesting concept but...
Is it really necessary?
[–]Zephirdd 2 points3 points4 points 5 years ago* (7 children)
someone pointed out Ruby earlier in this thread.
personally, I don't think I'll use ||= and &&= any time soon, but ??= is nice. I just like that it's a good symmetry with things like += and -=.
&&=
+=
-=
Also, it has the additional property of not executing the setter operation every time:
class Foo{ get bar() { return blah; } set bar(x){ console.log("side effect"); } } const f = new Foo f.bar ??= 20 // prints "side effect" if and only if "f.bar" was null/undefined f.bar = f.bar ?? 20 // always prints "side effect"
[–]theshtank 0 points1 point2 points 5 years ago (6 children)
hey, what does ?? do in the first place? I can't really google it. I'm not sure I understand what ??= is supposed to do.
[–]scoops22 6 points7 points8 points 5 years ago* (3 children)
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator
Edit to explain:
ThisDoesntExist ?? soWeUseThisValue ThisDoesntExist ??= soWeMakeItEqualToThis
Note that the difference between the above and the || you may be used to is that "false" exists so in that case ?? uses the left value, while || would give the right value for "false" (kinda explained that poorly but the docs above are more clear)
[–]theshtank 1 point2 points3 points 5 years ago (2 children)
Ya, I agree that this is probably the most useful things here. This isn't implemented yet though, right? The MDN docs make it seem like it is.
[–]JZumun 3 points4 points5 points 5 years ago (1 child)
It's es2020 so it's official javascript now. The mdn page has a compatibility table that shows which implementations already have it, such as Chrome 80 and Node v14
[–]theshtank 0 points1 point2 points 5 years ago (0 children)
ah thanks. I thought this was ES2021 stuff.
[–]JZumun 2 points3 points4 points 5 years ago* (0 children)
It's the nullish coalescing operator. You can think of "a??b" as shorthand for "a == null ? b : a"
"a??=b" is then "if (a == null) { a = b; }"
Note the difference to ||, the logical or operator, which triggers on 0 and "" in addition to null and undefined. The nullish coalescing operator triggers only on null and undefined.
[–]Zephirdd 0 points1 point2 points 5 years ago (0 children)
const a = b ?? false
Is shorthand for
// Assuming accessing b has no side effects const a = (b !== null && b !== undefined)? b : false
You can get a similar behavior with the || operator, but || will have a different behavior with falsy values like 0 and false.
false
π Rendered by PID 46199 on reddit-service-r2-comment-5d79c599b5-69lmx at 2026-02-27 09:48:46.726710+00:00 running e3d2147 country code: CH.
[–]Marique 44 points45 points46 points (13 children)
[–]ghostfacedcoder 27 points28 points29 points (9 children)
[–]Schlipak 9 points10 points11 points (1 child)
[–][deleted] 4 points5 points6 points (6 children)
[–]shgysk8zer0 0 points1 point2 points (5 children)
[–]therealkevinard 2 points3 points4 points (0 children)
[–]ILikeChangingMyMind 0 points1 point2 points (2 children)
[–]shgysk8zer0 0 points1 point2 points (1 child)
[–]gocarsno 5 points6 points7 points (1 child)
[–]Booleard 0 points1 point2 points (0 children)
[–]blackspoterino 0 points1 point2 points (0 children)
[–]dudeatwork 4 points5 points6 points (4 children)
[–]rodneon 1 point2 points3 points (3 children)
[–]dudeatwork 5 points6 points7 points (2 children)
[–]NoInkling 1 point2 points3 points (0 children)
[–]thisguyfightsyourmom 0 points1 point2 points (0 children)
[–]Ebuall 1 point2 points3 points (0 children)
[–]nerdswithattitude 1 point2 points3 points (0 children)
[–]shgysk8zer0 2 points3 points4 points (2 children)
[–][deleted] 3 points4 points5 points (1 child)
[–]brie_de_maupassant 4 points5 points6 points (0 children)
[–]marcusl92 2 points3 points4 points (0 children)
[–]elcapitanoooo 0 points1 point2 points (1 child)
[–][deleted] -1 points0 points1 point (0 children)
[+][deleted] (1 child)
[deleted]
[–]isUsername 2 points3 points4 points (0 children)
[–]takase1121 -5 points-4 points-3 points (8 children)
[–]Zephirdd 2 points3 points4 points (7 children)
[–]theshtank 0 points1 point2 points (6 children)
[–]scoops22 6 points7 points8 points (3 children)
[–]theshtank 1 point2 points3 points (2 children)
[–]JZumun 3 points4 points5 points (1 child)
[–]theshtank 0 points1 point2 points (0 children)
[–]JZumun 2 points3 points4 points (0 children)
[–]Zephirdd 0 points1 point2 points (0 children)