Create array and push into it in one line - javascript

The following is just a theoretical JavaScript question. I am curious if the following can be converting into a single statement:
if(!window.foo){
window.foo = [];
}
window.foo.push('bar');
everyone has probably written this code before, but can it be done in one line?
At first I thought something like this would work:
(window.foo || window.foo = []).push('bar');
but that doesn't work because of an invalid assignment. Next I tried chaining something on the push, but that doesn't work because push does not return the array.
Any thoughts on if this can be done in plain JavaScript?
(the result by the way should be that window.foo = ['bar'])

You've got your assignment backwards*. It should be:
(window.foo = window.foo || []).push('bar');
The || operator in JavaScript does not return a boolean value. If the left hand side is truthy, it returns the left hand side, otherwise it returns the right hand side.
a = a || [];
is equivalent to
a = a ? a : [];
So an alternative way of writing the above is:
(window.foo = window.foo ? window.foo : []).push('bar');
* see comments for details

Your code works just fine if you add parentheses so that it does what you intended:
(window.foo || (window.foo = [])).push('bar');
Without the parentheses, it thinks that it should evaluate window.foo || window.foo first, and then assign the array to the result of that, which is not possible.

This question got me playing with different options for fun. It's too bad push returns the length instead of the original array reference, but for even shorter expressions it can be helpful to have something that can be immediately iterated, mapped, etc.
window.foo = (window.foo||[]).concat(['bar']); // always returns array, allowing:
(window.foo = (window.foo||[]).concat(['bar'])).forEach( ... )
(window.foo = window.foo||[]).push('bar'); // always returns length
window.foo && window.foo.push('bar') || (window.foo = ['bar']); // playing around

2021 Update
#zzzzBov's helpful answer,
(window.foo = window.foo || []).push('bar');
can be further simplified using the new ||= operator, logical OR assignment1,
(window.foo ||= []).push('bar');
1 See tcs39/proposal-logical-assignment, currently in Stage 4, and supported by major browsers.

The shortest way to do this is using Logical Nullish Assignment:
(window.foo ??= []).push('bar');
Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_nullish_assignment

You can use .concat instead of .push, since .concat returns the array and .push returns the array's length.
window.foo = (window.foo || []).concat('bar');
This way the code is easier to read and understand.
Shorter version with a new ||= operator: (may be slightly harder to read though)
window.foo ||= [].concat('bar');

Related

Logical 'and' with object and value in javascript

In the book 'Functional javascript' by Michael Fogus, I faced with one expression that I still can't undrestand.
Here is the function:
function defaults(d){
return function(o, k){
var val = fnull(_.identity, d[k]);
return o && val(o[k]);
}
}
where
function fnull(fun /*, defaults*/){
var defaults = _.rest(arguments);
return function(/* args */){
var args = _.map(arguments, function(e, i){
return existy(e)?e : defaults[i];
});
return fun.apply(null, args);
};
};
function existy(x){return x != null}
(underscore is the object of Underscore.js library)
and the example of use:
function doSomething(config){
var lookup = defaults({critical:108});
return lookup(config, 'critical');
}
doSomething({critical: 9});
//=> 9
doSomething({});
//=> 108
I've recreated exapmle in node.js and it works fine, but I wonder why is the logical 'and' in the return line of 'default' function?
return o && val(o[k]);
What is the point of doing that? I checked the exapmle with
return val(o[k]);
and it also worked well.
It's hard to believe that this is just a mistake...
The logical and will make sure the second part is only evaluated if the first part is true. If o does not evaluate to true, the expression returns false. Otherwise, it returns val(o[k]).
This is used as a quick check to see if o is not false / null / undefined.
return o && val(o[k])
mean that if "o" is TRUE it will return "val(o[k])"
given "expr1 && expr2":
Returns expr1 if it can be converted to false; otherwise, returns expr2. Thus, when used with Boolean values, && returns true if both operands are true; otherwise, returns false.
That is smart usage of something called short "short-circuiting" in logical expressions.
As logical expressions are evaluated left to right, they are tested
for possible "short-circuit" evaluation using the following rules:
false && (anything) is short-circuit evaluated to false.
true ||(anything) is short-circuit evaluated to true.
The rules of logic guarantee that these evaluations are always correct. Note that the (anything) part of the above expressions is not evaluated (meaning not ran at all), so any side effects of doing so do not take effect. There are also benefits to it.
Usage:
Make your expressions evaluate faster by putting something easily calculable or likely to be true/fail at leftmost position in expression.
For example parOfExpressionLikelyToBeTrue && (rest of expression) will in most cases not even calculate the other part of expression. Same goes for parOfExpressionLikelyToBeTrue || (rest of espression).
Same can be used if something is very time consuming to calculate, you push it as far back to the right in expression. For example (rest of the expression) && ThisCostsALotOfTime or (rest of the expression) || ThisCostsALotOfTime. Here when first parts of expression short-circuit you save time on your time consuming part.
Short circuit existence evaluation. Lets say you need to check if your object's property pr is 3? What would you do? obj.pr === 3? Yes and no. What if property is missing? It's fine you will get undefined and that is not === 3. But what if object is not there. You will get trying to read pr of undefined error. You can use short-circuit logic here to you benefit by being defensive and writing the expression as if (obj || obj.pr === 3). This ensures there are no errors, only true and false.
Short circuit initialization. Let's say you wanna say variable a is b. But b might be undefined. And you wanna your variable to have a default. You could write a=b and then check if a is undefined and set it to default or you can be clever and write it as a = b || 3. This way a is b or if be is undefined it's 3. Ofc, you can use this for late initialization as well a = a || 3.
Making sure object for function exists before trying to run function. Same as before mentioned with properties you might wanna test if object containing the function exists before running the function. Let's say you got object obj and function fn as it's property. You might call that function like obj.fn(). It's fine, but if obj is undefined you will get an error. Being defensive you might wanna write: obj && obj.fn().
Running the function only if there is one. Since functions in JS can be passed to other functions you can not be sure at run time it's there. Being defensive you might wanna run your function as (typeof passedFunction === "function" && passedFunction() instead just passedFunction() which my produce an error.
other smart things like guardian expressions etc which are complicated and too many to for me to remember all and you should avoid them anyway for better code readability.

JavaScript variable assignment with OR vs if check [duplicate]

This question already has answers here:
What does the construct x = x || y mean?
(12 answers)
Closed 6 years ago.
In JavaScript I recently realized you could use the OR || logical operator for assignment, and I want to know if it's considered bad practice.
In particular I have some functions that have optional array input, if the input is null or undefined I should just set it to an empty array [], if it has content it should take the content.
I found that using the assignment using the OR operator handles that perfectly in a single line, it's clean. However, it feels like the kind of thing that might be considered bad practice, or may have some horrible pitfalls I'm not considering.
Another approach is a simple if check, which is fairly safe in general.
I want to know if using the || approach seen below has any pitfalls I'm not considering, although it works in this scenario I would appreciate knowing if it works well to keep using this in the future, or to stop using it altogether.
https://jsbin.com/nozuxiwawa/1/edit?js,console
var myArray = ['Some', 'Strings', 'Whatever'];
// Just assign using OR
var pathOne = function(maybeAnArray) {
var array = maybeAnArray || [];
console.log(array);
}
// Assign using IF
var pathTwo = function(maybeAnArray) {
var array = [];
// Covers null and undefined
if (maybeAnArray != null) {
array = maybeAnArray;
}
console.log(array);
}
console.log('Path one:');
pathOne(myArray); // ['Some', 'Strings', 'Whatever']
pathOne(null); // []
console.log('\nPath two:');
pathTwo(myArray); // ['Some', 'Strings', 'Whatever']
pathTwo(null); // []
IMHO the use of the OR || for the purposes of assignment is perfectly valid and is good practice. We certainly use it in our projects and I've seen it used in lots of 3rd party projects that we use.
The thing you need to be aware of is how certain JavaScript objects can be coerced to be other values. So for example, if you're ORing values such as "", false or 0 then they are treated as false... this means that when you have the following:
function f(o) {
var x = o || -1;
return x;
}
Calling:
f(0)
...will return -1... but calling
f(1)
Will return 1 ... even though in both cases you passed a number - because 0 is treated as false -1 is assigned to x.
...that said, as long as you're aware of how the OR operator will treat the operands that you use with it - then it is good JavaScript practice to use it.
i prefer the first option, it's clear for my eyes, but when i need to share my code with others will think about to use second, will be more clear for any.
Now i'm using sonar, and prefer the second option too, will more easy to comprend for machine in inegration works.
Last idea is to use
if(maybeAnArray !== void(0))
Two reasons:
use cast and type conditionals
void(0) will works same for all browsers
Expect it helps yopu
When given the option, I prefer concise code (which must still be readable).
I would say || is common enough that it is considered good practice. Once one has seen it a few times it reads just fine.
In my opinion there are few reasons why you should rather use the second option:
First of all it's much more readable - new developers that are still learning can have problems with understanding notation like var myArray = someArrayArg || [];
If you are using some kind of code checkers like JSLint, they will return warnings and/or errors like Expected a conditional expression and instead saw an assignment. for the statement with var myArray = someArrayArg || [];
We already have something like var myArray = someArrayArg ? someArrayArg : []; that works pretty well

scala : how to inititialize a val with a check

In javascript there the logical OR is super useful in :
Given:
var sth = null;
var obj = sth || {}; // obj will be an empty object
var obj2 = sth || 'a'; // obj2 will be 'a'
is there anything similar for scala?
If an object may or may not exist, then it should be wrapped in an Option[A] - in which case, you can use getOrElse
val userOpt: Option[User] = db.getUser(id)
val user: User = userOpt getOrElse defaultUser
If you're talking about an arbitrary condition, then use:
val obj = if(condition) x else y
The most direct answer to this is the second part of what dcastro said about using an if expression on the left side of the equal sign.
val obj = if(condition) x else y
I wanted to elaborate some on that. I expect that the author of the question and others who like the approach used in JavaScript, Python, and other dynamic languages might find this to be verbose and prefer the use of || instead. The problem with this is that it only works when you are working in a language with little to no static type safety. In a language with good type safety, || is an operator that works on booleans and results in a boolean. Giving it arguments that aren't booleans is a type error. The || shortcut in JavaScript and other scripting languages only works because the arguments to || do not have to be boolean and all values have a natural 'truthy' or 'falsy' nature.

Ruby's ||= (or equals) in JavaScript?

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 = {};
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 :)
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
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.
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.
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.
Logical nullish assignment (??=)
x ??= 23
Documentation & Browser compatibility
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
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]

Calling javascript function with an objectstring in dot notation

Suppose I have the string:
var string = "function";
With
window[string];
I can call a function with the name of "function".
But, when I have:
var string2 = "function.method.weHaveTogoDeeper";
it should call
window["function"]["method"]["weHaveTogoDeeper"]
I can't do:
window[string2]
in this case. I dont know the number of "." in the string, so I need some kind of routine.
you can split the string across . by using the String.split method:
var string2 = "function.method.weHaveTogoDeeper";
var methods = string2.split(".");
In this examples, methods will be the array ["function","method","weHaveTogoDeeper"]. You should now be able to do a simple iteration over this array, calling each function on the result of the previous one.
Edit
The iteration I had in mind was something like this:
var result = window;
for(var i in methods) {
result = result[methods[i]];
}
In your example, result should now hold the same output as
window["function"]["method"]["weHaveTogoDeeper"]
function index(x,i) {return x[i]}
string2.split('.').reduce(index, window);
edit: Of course if you are calling functions from strings of their names, you are likely doing something inelegant which would be frowned upon, especially in a collaborative coding settings. The only use case I can think of that is sane is writing a testing framework, though there are probably a few more cases. So please use caution when following this answer; one should instead use arrays, or ideally direct references.
I wrote one a while back:
function RecursiveMapper(handlerName, stack) {
// check if empty string
if(!handlerName || handlerName === '' || (handlerName.replace(/\s/g,'') === '')) return null;
var buf = handlerName.split('.');
stack = stack || window;
return (buf.length === 1) ? stack[buf[0]] : this.RecursiveMapper(buf.slice(1).join('.'), stack[buf[0]]);
}
Call it like this: RecursiveMapper(window[string2]);
This one also checks if the function is defined in window scope first and returns the global one fi found.

Categories