"arguments" keyword in JavaScript - javascript

const add = (x=5, y=10) => console.log(x+y);
After we run the transpiler on this code, here is what the output would look like:
"use strict";
var add = function add() {
var x = arguments.length <= 0 || arguments[0] === undefined ?
5 : arguments[0];
var y = arguments.length <= 1 || arguments[1] === undefined ?
10 : arguments[1];
return console.log(x + y);
};
I got this snippet from Learning react book.
I have two question here
Can arguments.length be negative?
Does checking the second "||" condition be sufficient to check whether arguments[0] or arguments[1] is undefined?

Can arguments.length be negative?
No. How could you call a function and put a negative number of things between ( and )?!
Does checking the second condition be sufficient?
No. The function might be called with only one argument.

Related

What does the first operand on var __decorator = (this && this.__decorate) || function() {...} try to do?

When TypeScript decorator (class-decorator) gets transpiled to JavaScript it yields this:
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Now, what gets assigned to var __decorate variable when the (this && this.__decorate) returns true?
Also, if it gets abandoned how does it affect the whole code?
JS does not nessesarily return true or false from a logical statement. A || B will return A if it is truthy or B if A is falsy. Similarly A && B will return A if it is falsy and B otherwise.
Both || and && are also so-called short-circuit operators where the second operand is not even executed if it is not needed in order to determine the result. So (A && A.B) is often used to get the value of A.B while guarding against A being undefined, or A = B || C used to set A to B if it is defined, or to declare the definition C if it is not.
See, for example, MDN for more details.
(this && this._decorate) looks like it is checking if _decorate is already defined on this. First it is checking if this is defined (otherwise an error would be thrown) then checking the value. If this._decorate is already defined then the function declaration will be skipped (as the existing this._decorate function will be truthy as all functions are).
The only JS operator which is guaranteed to return an actual boolean value is the not operator !.

Javascript comma syntax, and complex expressions, minified, obfuscated: please help me understand a piece of code

I need to understand some pieces of code. I feel fine with the syntax of Java, C++, PHP, but Javascript syntax is still a "dark forest" for me. Here are the original forms and possible interpretations, I mean equivalents in terms of program logic:
1.
var o,
a,
s = "https://widget.kiwitaxi.com",
c = e.createElement("iframe"),
l = e.getElementById(r.target),
p = r && r.height_bias ? 4 + r.height_bias : 4,
u = !1,
f = parseInt(r.min_height, 10) ? parseInt(r.min_height, 10) : r.hide_form_extras && !r.default_form_title ? 304 : 386;
I'm almost sure about this one, here I can replace commas with semicolons and add VAR statement to the beginning of each line and it will produce the same results, am I right?
var o;
var a;
var s = "https://widget.kiwitaxi.com";
var c = e.createElement("iframe");
var l = e.getElementById(r.target);
var p = r && r.height_bias ? 4 + r.height_bias : 4;
var u = !1;
var f = parseInt(r.min_height, 10) ? parseInt(r.min_height, 10) : r.hide_form_extras && !r.default_form_title ? 304 : 386;
And this one is really tough for me, I cannot presume any interpretation
As I understand:
"o" is evaluated to s + "/w", then is concatenated with "-", and then with ".html" ? Are any conditions applied to that string building, I mean, can any of that two concatenations be applied by condition in this code ?
What does comparison == operator do in the statement (the part "en" == r.language...), which variable receives that result ? Or can it be just an obfuscation trick ?
And the last one, after the last comma, r.banner_id || (r.banner_id = "22995c4e"); Here goes an assignment, that is clear, but what is the point of other stuff in this part ? Is the assignment made by condition here (if r.banner is not undefined-or-null-or-false) ?
o = s + "/w",
"en" == r.language && (o += "-" + r.language.toString().toLowerCase()),
("biletik" == r.theme || "ostrovok" == r.theme) &&
(o += "-" + r.theme.toString().toLowerCase()),
o += ".html",
r.banner_id || (r.banner_id = "22995c4e");
"en" == r.language && (o += "-" + r.language.toString().toLowerCase()),
Ooh...that line's tricky.
So, example: If you were to write var myVar = false && thisFunctionThrowsError(), where the function would throw an exception if it were called, that would actually not return an error - because anything after the ampersand won't be evaluated. It's called short-circuit evaluation. In this case, someone has cut out the part where he checks the result of the && comparison, and only uses it to determine whether or not to run the right side.
So, if I write:
"biletik" == r.theme && (o += "-");
That means it will add a dash to o only if r.theme == 'biletik'.
The last line is the opposite; it looks like it's a lazy-initializer. If r.banner_id is null, that evaluates to false - so it runs the second part of the ||, initializing it to 22995c4e.

Extended Ternary expression

I know you can do ternary expressions in Javascript for an if - else statement, but how about an else- else if- else statement? I thought that surely this would be supported but I haven't been able to find any info about it and wasn't able to get it to work just hacking around.
In contrast to Robby Cornelissen's answer - there is no problems with readability if you format it properly (and not writing PHP, since it messed up the operator by making it left-associative in contrast to all other languages that have that construct):
var y =
x == 0 ? "zero" :
x == 1 ? "one" :
"other";
EDIT
What I was looking for is a shorter version of "if expression 1 is true, return expression 1. Else if expression 2 is true, return expression 2. Else return expression 3". Is there no clean way to do this?
There is: expression1 || expression2 || expression3. (It would have been nice if you had put this into your question in the first place.) This is commonly used for default values:
var defaults = null;
function hello(name) {
var displayName = name || (defaults && defaults.name) || "Anonymous";
console.log("Hello, " + displayName + ".");
}
hello("George");
// => Hello, George.
hello();
// => Hello, Anonymous.
defaults = {};
hello();
// => Hello, Anonymous.
defaults.name = "You"
hello();
// => Hello, You.
However, it is important to be aware of the conditions for truthiness. For example, if you expect "" or 0 to be a valid value that does not need to be replaced by a default, the code will fail; this trick only works when the set of possible non-default values is exactly the set of truthy values, no more and no less. E.g.
function increment(val, by) {
return val + (by || 1); // BUG
}
increment(10, 4);
// => 14
increment(10, 1);
// => 11
increment(10);
// => 11
increment(10, 0);
// => 11 <-- should be 10
In this case you need to be explicit:
function increment(val, by) {
return val + (typeof(by) === "undefined" ? 1 : by);
}
I wouldn't recommend it because of readability, but you could just nest ternary operators:
var y = (x == 0 ? "zero" : (x == 1 ? "one" : "other"));
This would be the equivalent of:
var y;
if (x == 0) {
y = "zero";
} else if (x == 1) {
y = "one";
} else {
y = "other";
}
You can extend a ternary condition if you're good. It gets to be messy though.
var number = 5;
var power = 2;
var ans = Math.pow(number,power);
var suggest = ( ans == 5 ? 5 : ans == 10 ? 10 : ans == 15 ? 15 : ans == 25 ? "works" : null);
console.log(suggest);
I may have added to many because I'm on my phone haha but try it in your developer panel.

|| ('OR') operator alternative

I obviously got something terribly wrong here so I'll appreciate any good 'ol advice.
How come that if I write
var x='';
var y="12345";
(y.substring(0, 3) === "000"||"999") ? x=1: x=0;
console.log (x, y.substring(0, 3));
The answer would be 1 "123"
instead of 0 "123"?
Thanks y'all!
First the ternary operator syntax is not how you use it normally and you'll have to make two comparisons instead of one.
var str = y.substring(0, 3);
x = (str === "000"|| str === "999") ? 1 : 0;
MDN
For condition ? expr1 : expr2
If condition is true, the operator returns the value of expr1;
otherwise, it returns the value of expr2.
The or operater works like this: a || b
Where each statement is isolated from eachother, basically you can make i more visible like this:
var c1 = y.substring(0, 3) === "000";
var c2 = "999";
if ( c1 || c2 ) { x = 1; } else { x = 0; };
See the problem here?
I would rewrite your statement so something like this:
x = ["000", "999"].indexOf(y.slice(0, 3)) > -1 ? 1 : 0;
Note how I'm using Array.prototype.indexOf to test multiply cases:
["000", "999"].indexOf(y.slice(0, 3)) // returns the index of the array or -1 if not in the array.

What's the difference between these two uses of the && logical operator?

What is the difference between these various uses of the "&&" logical operator?
From Oliver Steele's Functional.js library.
Line 4, "args.length && arg":
0 Function.prototype.partial = function(){
1 var fn = this, args = Array.prototype.slice.call(arguments);
2 return function(){
3 var arg = 0;
4 for ( var i = 0; i < args.length && arg < arguments.length; i++ )
5 if ( args[i] === undefined )
6 args[i] = arguments[arg++];
7 return fn.apply(this, args);
8 };
9 };
From bootstrap.js.
Line 11 below, "'hover' && this.$element":
1 var Carousel = function (element, options) {
2 this.$element = $(element).on('keydown.bs.carousel', $.proxy(this.keydown, this))
3 this.$indicators = this.$element.find('.carousel-indicators')
4 this.options = options
5 this.paused =
6 this.sliding =
7 this.interval =
8 this.$active =
9 this.$items = null
10
11 this.options.pause == 'hover' && this.$element
12 .on('mouseenter.bs.carousel', $.proxy(this.pause, this))
13 .on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
14 }
Also why not just use the + arithmetic operator in the first example?
Here is yet another example that I'm having trouble grokking, from the same Carousel section of bootstrap.js:
this.options.interval
&& !this.paused
&& (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
Well, it's the same operator everywhere, but being used for different purposes by the programmer.
The first code example is not doing args.length && arg at all, but is rather doing the equivalent of (i < args.length) && (arg < arguments.length) because && has lower precedence than <. It means, "loop until either i is at or surpasses the argument count or arg is at or surpasses the argument count". You can see that + is therefore not equivalent in this context.
The other code examples are all exploiting the fact that the logical-and operator (&&) "short-circuits" when its left-hand operand is false, i.e. it only evaluates the expression on the right if the one on the left is true.
So, this.options.pause == 'hover' && this.$element.on(... is a short-hand way of attaching the event listeners only if the pause option is set to 'hover' (because if it's not, the left-hand expression will be false, and the on functions won't be called).
Similarly, the final example you found only calls setInterval (and assigns the result to this.interval) if the desired interval is "true" (I imagine generally non-zero here, but also not undefined, etc.) and the carousel is not paused.

Categories