132

I love Ruby's ||= mechanism. If a variable doesn't exist or is nil, then create it and set it equal to something:

amount # is nil
amount ||= 0 # is 0
amount ||= 5 # is 0

I need to do something similar in JavaScript now. What's the convention or proper way to do this? I know ||= is not valid syntax. 2 obvious ways to handle it are:

window.myLib = window.myLib || {};

// or

if (!window.myLib)
  window.myLib = {};
rogerdpack
  • 50,731
  • 31
  • 212
  • 332
at.
  • 45,606
  • 92
  • 271
  • 433

8 Answers8

154

Both are absolutely correct, but if you are looking for something that works like ||= in ruby. The first method which is variable = variable || {} is the one you are looking for :)

Syed Aslam
  • 8,387
  • 5
  • 39
  • 53
Dzung Nguyen
  • 8,760
  • 13
  • 61
  • 98
  • 3
    Careful using this if a valid value for `x` is falsy, like `false`, and you only want to set a default when `x` is undefined. – Joshua Pinter Jul 31 '20 at 20:36
  • above comment is right. Taking your example case , it will not work the same way in JS. `let amount = 0;` followed by `amount = amount || 5` will change amount to 5. If you dont want that to happen use `??` operator instead of `||` . – AshwinKumarS Aug 04 '20 at 18:56
  • @AshwinKumarS Or just use `amount ??= 5;`. – Sebastian Simon Aug 04 '20 at 21:50
  • @user4642212 I dont think that syntax works in JS, does it ? – AshwinKumarS Aug 05 '20 at 19:55
  • 1
    @AshwinKumarS Yes, it does. See the [documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_nullish_assignment), [specification](https://tc39.es/ecma262/#sec-assignment-operators-runtime-semantics-evaluation), [proposal](https://github.com/tc39/proposal-logical-assignment/). – Sebastian Simon Aug 05 '20 at 20:03
  • @user4642212 interesting, i tried to run the demo there in docs page but got an error `Error: Unexpected token '='` – AshwinKumarS Aug 05 '20 at 20:09
  • @AshwinKumarS The documentation link includes a browser compatibility table. – Sebastian Simon Aug 05 '20 at 20:10
  • @user4642212 geez bummer. thanks...sadly doesn't work with node as well..for now. – AshwinKumarS Aug 05 '20 at 20:11
22

You can use the logical OR operator || which evaluates its right operand if lVal is a falsy value.

Falsy values include e.g null, false, 0, "", undefined, NaN

x = x || 1
janniks
  • 2,300
  • 3
  • 16
  • 29
Moritz Roessler
  • 8,014
  • 22
  • 50
  • Careful using this if a valid value for `x` is falsy, like `false`, and you only want to set a default when `x` is undefined. – Joshua Pinter Jul 31 '20 at 20:36
6

The operator you asked about has been proposed as a feature in JavaScript. It is currently at Stage 4, and it will be introduced in the next ECMAScript standard, which is expected to be published in 2021.

You can use it now using the plugin-proposal-logical-assignment-operators Babel plugin. I have never used that plugin, so I have no idea how well it works.

Elias Zamaria
  • 80,938
  • 29
  • 103
  • 136
  • 6
    Update: the proposal is now [finished](https://github.com/tc39/proposals/blob/master/finished-proposals.md), i.e. it has reached Stage 4 and is included in the latest draft of the ECMAScript specification. It will be included in the next standard, which will be published in 2021. – Rory O'Kane Oct 09 '20 at 16:02
5

If you're working with objects, you can use destructuring (since ES6) like so:

({ myLib: window.myLib = {} } = window);

...but you don't gain anything over the accepted answer except confusion.

Inkling
  • 2,656
  • 3
  • 24
  • 38
0

Logical nullish assignment (??=)

x ??= 23

Documentation & Browser compatibility

Igor Sukharev
  • 641
  • 9
  • 11
0

As of 2021, you can use ||= with identical behavior to Ruby as long as you are transpiling or don't care about Opera/IE.

Logical OR assignement, ||= is now supported natively in javascript on all major browsers except Opera and IE. Current caniuse matrix. MDN reference.

Typescript added support for the operator in version 4. If you need to support IE/Opera you can use the babel plugin to transpile for broad compatibility.

Matt Sanders
  • 5,693
  • 1
  • 26
  • 38
-1

Ruby's ||= operator short circuits assignment. It can be thought of like this:

return a || a = b

So in javascript, this looks very similar:

return a || (a = b);

It seems as pointed out in the comments below however, that this literal ruby form is less efficient than the standard javascript idiom a = a || b.

For reference: http://www.rubyinside.com/what-rubys-double-pipe-or-equals-really-does-5488.html

chris
  • 5,365
  • 5
  • 38
  • 52
  • 1
    In practice it seems that the `a = a || b` form is more optimal http://jsperf.com/x-or-x-equals-0-vs-x-equals-x-or-0/3 – jchook Mar 06 '16 at 16:47
  • ah cool tool. what does it look like if x has a value and so short circuits? – chris Mar 08 '16 at 00:53
  • I believe teardown needs to be explicit on jsperf so [this test](http://jsperf.com/x-or-x-equals-0-vs-x-equals-x-or-0/4) should show the short circuit performance. My guess is that V8 has a special optimization for the form `a = a || b`. – jchook Mar 09 '16 at 02:31
  • 3
    FYI It looks like whatever difference there was has now been optimized away. – Charles Wood Feb 08 '19 at 16:52
  • `a || (a = b)` has the correct semantics to infer function names. It’s currently under [discussion](https://github.com/tc39/proposal-logical-assignment/issues/23) for the new proposal. – Sebastian Simon May 05 '20 at 17:23
  • UPDATE: https://devblogs.microsoft.com/typescript/announcing-typescript-4-0-beta – chris Jun 27 '20 at 19:51
-1

You can achieve the desired behaviour using |= operator in javascript for integers only. But you have to define the variable first.

let a = 0
a |= 100
console.log(a) // 100

For objects

let o = {}
o.a |= 100
console.log(o) // {a: 100}

For Arrays

let arr = []
arr[0] |= 100
console.log(arr) // [100]
wallgeek
  • 629
  • 1
  • 7
  • 9