What do these characters do in Javascript [duplicate] - javascript

This question already has answers here:
JavaScript plus sign in front of function expression
(4 answers)
Closed 8 years ago.
I was going through a piece of code here http://cssdeck.com/labs/bjiau4dy and I saw this in the Javascript box -
!+-+-+!+-+-+!+-+-+!+-+-+!+-+-+!+-+-+!+-+-+!+-+-+!
What does that do ? and why does it not throw errors in the console ?
Thanks!

Any of those symbols turn the function that follows it into a function expression, instead of a function declaration. Putting them all in there together is just for fun.
If you try to call a regular function by putting () right after the declaration:
function () {
// this is a syntax error...
}();
you'll get a syntax error:
SyntaxError: Unexpected token (
since you cannot call a function declaration.
So people usually wrap an anonymous function in parentheses to turn it into a function expression:
(function () {
// this will execute immediately
}());
You can achieve the same thing be prepending any of those symbols:
!function () {
// this will also execute immediately
}();
For more information, see here: http://kangax.github.com/nfe/#expr-vs-decl

There is zero point to doing the long set of symbols except as a stylistic watermark.
That set of symbols acts as an operation on the function that follows, but does nothing.
In JS you can write 1 or +1 (one) or !1 (false) or !+1 (still false). This is just a long chain of those that are acting on the following function.
So !+-+-+!+-+-+!+-+-+!+-+-+!+-+-+!+-+-+!+-+-+!+-+-+!1 doesn't throw an error. Its value is false though.
And !+-+-+!+-+-+!+-+-+!+-+-+!+-+-+!+-+-+!+-+-+!+-+-+!function(){ ... } just executes the function and evaluates to false (but nothing is done with the value anyway)
However, since something is there, it turns the function definition into an operation and evaluates the function immediately. But just +function(){ ... } would do the same thing.

To elaborate a bit more, each of these operators will actually perform type coercion on the operand proceeding it. + will convert the operand following it into a number, as will the - operator. ! is the not operator, and will convert the operand into a boolean (true/false).
Another thing to bear in mind is that in Javascript, everything can have evaluate to some kind of value. That could be a "truthy" or "falsey" value, and can also have a "number" value (even if that value is not a number, AKA NaN).
So, if you open up JSFiddle, or Firebug, and mess around with what these values do to functions, you can see that they'll also yield some kind of new return value.
For example:
!function(){} will evaluate to a value of false (since coercing a function object to a boolean yields a value of true).
+function(){} will evaluate to a value of NaN (since coercing a function object to a number yields NaN). The same result can be seen by using -.
!+function(){} yields true (coercing a number of value NaN will yield false and not false yields true.
!+-+-+!function(){} yields true (because !function(){} yields false, +false yields 0, and will continue to throughout all those + and - operators until finally !0 is evaluated to true).
Applying the operators like they're listed in your example will go back and forth between false, -1, 0, 1, true until all of the operators have been evaluated.
Note that I checked these using Firebug. There could possibly be differences between browsers, and perhaps what Firebug shows us on evaluation. The TL;DR is that Javascript does lots of type coercion, and will evaluate expressions differently than declarations.

Related

Odd behaviour of comparison of object literals

I have searched but could not find logic behind following in JavaScript.
When I type in the Chrome console:
{} == null
it returns
Uncaught SyntaxError: Unexpected token ==
But
{} == {}
and
{} == function(){}
returns false
Why?
I assume you understand why {} == null throws SyntaxError. Long story short it is because { in the begining starting a block statement not an object literal. You could check the answer here
As of why {} == {} this works.
If you check chromium code that evaluates expressions in console. You could find the following (code)
if (/^\s*\{/.test(text) && /\}\s*$/.test(text))
text = '(' + text + ')';
executionContext.evaluate(text, "console", !!useCommandLineAPI, false, false, true, printResult);
This code wraps {} == {} code with parentheses making it a valid expression ({} == {}) comparing two empty object literals. Which evaluates to false because objects are compared by reference.
Node repl has the same behaviour src
if (/^\s*\{/.test(code) && /\}\s*$/.test(code)) {
// It's confusing for `{ a : 1 }` to be interpreted as a block
// statement rather than an object literal. So, we first try
// to wrap it in parentheses, so that it will be interpreted as
// an expression.
code = `(${code.trim()})\n`;
wrappedCmd = true;
}
You can find this in the specs under Statement (art. 12)
12 - Statement
Statement :
Block.
VariableStatement
EmptyStatement
ExpressionStatement
.
.
.
The first applicable rules are either Block or Expression Statement. So we need to look at 12.4.
In 12.4 the specs clearly state that an expression statement cannot start with a {.
though i haven’t yet found what makes example 2 an expression, maybe it’s implementation specific
12.4 Expression Statement
Syntax
ExpressionStatement :
[lookahead ∉ {{, function}] Expression ;
NOTE An ExpressionStatement cannot start with an opening curly brace because that might make it ambiguous with a Block. Also, an ExpressionStatement cannot start with the function keyword because that might make it ambiguous with a FunctionDeclaration.
Semantics
The production ExpressionStatement : [lookahead ∉ {{, function}]Expression; is evaluated as follows:
Let exprRef be the result of evaluating Expression.
Return (normal, GetValue(exprRef), empty).
I would say this is a parsing issue, rather than a logic issue per se.
In Chrome I get the observed behavior.
In IE I get syntax errors whenever I put {} (or, it seems, any object literal) on the LHS of the ==.
In both browsers, putting () around the expression fixed things. Or first assigning the object to a variable
var x = {}
x == null
I would say it seems to me like a bug in the parsing. Whether that is true in an academic sense would take digging through specs and grammars; the practical answer is, there are simple enough work-arounds that the best bet is to not do that.
It’s because JavaScript sucks
The reason it doesn’t work is because
JavaScript takes the type the comparison is taking from the first object.
For instance
3+”1” = 4
But
“3”+1 = 31
The first example does the operation as a number because the first object is a number
The second example sees a string as the first object and treats the operation as concatenation of a string.
For your example
{} is an object but null can’t be converted to an object
It works the other way because
{} can be represented as a null object.

Calling a JavaScript function that returns a Boolean

* EDITED *
REF: Calling a JavaScript function that returns a Boolean [on hold]
function booleanFunction()
{
if (something) return true;
else return false;
}
My original question was "When calling a Boolean Function, is it correct to say?":
if (booleanFunction)
or
if (booleanFunction())
I had previously read that the first choice was correct. Your voluminous responses said otherwise.
Based on all that I have learned from all your responses, I conclude:
(1) if (booleanFunction) is truthy in the sense that this if statement will ALWAYS return true. In other words, this if statement is equivalent to asking if this booleanFunction EXISTS, independent of its correctness.
(2) to evaluate the value (true or false) returned by the booleanFunction, I need to say if (booleanFunction()).
Have I concluded correctly?
The text you quote is outright incorrect.
To call a function, use parentheses. If the function takes no arguments, the call looks like booleanFunction() and returns a value.
To evaluate a value, put it into parentheses. In an if-statement, while-loop, a value is converted to a boolean automatically, the same as (new Boolean( SOME_VALUE )).valueOf() or !! (SOME_VALUE). Refer to MDN for the full conversion rules. For instance,
if (booleanFunction()) {
is perfectly fine, but
if (booleanFunction) {
would convert the value of booleanFunction to boolean, and that is true, because any function object will be converted to true.
I have edited my original question. Hopefully, it is now totally clear.

Why I'm not getting an error when checking the length of null [duplicate]

This question already has answers here:
Does a javascript if statement with multiple conditions test all of them?
(10 answers)
Closed 6 years ago.
I'm checking the number of digits in a string using the match and length properties. Here is the codepen with my function http://codepen.io/PiotrBerebecki/pen/redMLE
Initially when returning numberOfDigits.length I was getting an error message (Cannot read property 'length' of null). I've solved this issue by changing the line to (numberOfDigits && numberOfDigits.length).
This works but I would like to get a better understanding why the new statement can be executed now. Does the interpreter execute the `numberOfDigits.length now?
Also, why are we getting the same errors when the operands are reversed (numberOfDigits.length && numberOfDigits)?
Here is the full JavaScript code:
function checkLength(str) {
let numberOfDigits = str.match(/\d/g);
return (numberOfDigits && numberOfDigits.length);
}
console.log( checkLength('T3xt w1th sOme numb3rs') );
console.log( checkLength('Text with some numbers') );
UPDATE 1:
The answers below explained that:
The order of the operands in the && expression counts.
JavaScript optimises the && operator and if the first operand evaluates to null then JavaScript does not check the second one as the expression cannot evaluate to nothing else than null / false.
JavaScript tries to optimise the && operator:
numberOfDigits && numberOfDigits.length
If numberOfDigits is a falsy value (and null is falsy), then the entire expression will be falsy and there is no need to evaluate numberOfDigits.length.
Falsy values are: undefined, null, 0, '', false, NaN. One way to check if something is falsy is to use the Boolean(falsyValue) === false (or more practical but less verbose ! falsyValue).
This is a side effect of the && operator. I can recommend to avoid using it and transform the code to something readable:
function checkLength(str) {
let numberOfDigits = str.match(/\d/g);
return Array.isArray(numberOfDigits) ? numberOfDigits.length : 0;
}
"Does the interpreter execute the `numberOfDigits.length now?"
No, JavaScript short-circuits logical expressions - as soon as result is known (i.e. first operand in and is falsy or first operand in or is truthy), no further operations are executed in the expression.
Docs: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_Operators
also, beware: && and || do not necessarily return Booleans in JavaScript
the reason is that when the interpreter sees two operations connected with a logical and (&&) it will first execute the former, and only if it is evaluted to true then it will execute the latter.
that is why since it found numberOfDigits to be null, which in JS is equivalent to false, it stops execution and never crashes on numberOfDigits.length.
the other way around will, of course, crash.
on a logical OR (||) the interpreter will stop evaluating after the first statement to be true.
I believe the reason is that the order of conditions counts.
The numberOfDigits condition gets evaluated first, so if that is false, the rest of the conditions are not evaluated and you won't get an error.
In the other order you would try to read "length" property of null, generating an error.
"And" logic will be executed as below.
true & true = true
false & anything = false`
If first condition fails then there is no point of executing second one.
so it wont execute numberOfDigits.length if numberOfDigits is null or undefined so no error in the below case.
(numberOfDigits && numberOfDigits.length) => false
false && anything => false
In same way if first condtion is not null then it will execute second condition.
(numberOfDigits && numberOfDigits.length) => true
true && true (must be) => true
Note : In javascript null and undefined are interpreted as false
in conditional statements.

Is it incorrect to use eval() within this function? Can I accomplish the same functionality without it somehow?

I'm trying to write a function I can use to test all for falsy values, keeping it concise since it will be run quite often serverside.
function is_falsy(val){
val = eval(String(val).toLowerCase());
return !!val;
}
I wonder if there's any way it could be done shorter, or what the possible negative implications of using eval() might be. JSBIN tells me it is "evil".
JSBIN
Assuming that val is a string that represents a JavaScript literal then we can take advantage of the fact that the only false-y values in JavaScript are:
0 (+ or -)
NaN
the empty string ('') or ("")
null
undefined
false
Thus, ignoring edge-cases (like 0.0) we could write it like so (a lower case can be performed as in the original code):
function is_falsey_literal (lit) {
if (['""', "''", "null", "undefined", "false", "0", "NaN"].indexOf(lit) >= 0) {
return true;
}
// Ideally there are more checks on numeric literals such as `-0` or `0.0`.
return false;
}
If needing to check a full expression then eval may "work" and is likely more practical when compared to writing a full JavaScript-in-JavaScript parser. For instance, in the above, the input string of (void 0) will be "true" although it evaluates to undefined which is definitely not a truth-y value.
Of course, perhaps the original data can be written/consumed such that there is no need for such a construct at all ..
There should never be any need to treat a string containing false or undefined as falsy. Doing so is inviting false positives (or false negatives) on possibly completely unrelated data.
Imagine what else would be treated as "falsy":
!true
!1
!!true
it's begging for mysterious bugs in your application further down the line.
The program flow should make sure that an undefined value actually arrives at your testing script as a literal undefined, not a string "undefined".
If you only want to test is falsy, then the below is enough.
function is_falsy(val){
return !val;
}
If you want to test whether a string is falsy value like 'false', then
function is_falsy(val){
try {
return !JSON.parse(String(val).toLowerCase());
} catch(e) {
return false;
}
}

Can someone explain this 'double negative' trick? [duplicate]

This question already has answers here:
What is the !! (not not) operator in JavaScript?
(42 answers)
Closed 8 years ago.
I am by no means an expert at Javascript, but I have been reading Mark Pilgrim's "Dive into HTML5" webpage and he mentioned something that I would like a better understanding of.
He states:
Finally, you use the double-negative trick to force the result to a Boolean value (true or false).
function supports_canvas() {
return !!document.createElement('canvas').getContext;
}
If anyone can explain this a little better I would appreciate it!
A logical NOT operator ! converts a value to a boolean that is the opposite of its logical value.
The second ! converts the previous boolean result back to the boolean representation of its original logical value.
From these docs for the Logical NOT operator:
Returns false if its single operand can be converted to true; otherwise, returns true.
So if getContext gives you a "falsey" value, the !! will make it return the boolean value false. Otherwise it will return true.
The "falsey" values are:
false
NaN
undefined
null
"" (empty string)
0
Javascript has a confusing set of rules for what is considered "true" and "false" when placed in a context where a Boolean is expected. But the logical-NOT operator, !, always produces a proper Boolean value (one of the constants true and false). By chaining two of them, the idiom !!expression produces a proper Boolean with the same truthiness as the original expression.
Why would you bother? Because it makes functions like the one you show more predictable. If it didn't have the double negative in there, it might return undefined, a Function object, or something not entirely unlike a Function object. If the caller of this function does something weird with the return value, the overall code might misbehave ("weird" here means "anything but an operation that enforces Boolean context"). The double-negative idiom prevents this.
In javascript, using the "bang" operator (!) will return true if the given value is true, 1, not null, etc. It will return false if the value is undefined, null, 0, or an empty string.
So the bang operator will always return a boolean value, but it will represent the opposite value of what you began with. If you take the result of that operation and "bang" it again, you can reverse it again, but still end up with a boolean (and not undefined, null, etc).
Using the bang twice will take a value that could have been undefined, null, etc, and make it just plain false. It will take a value that could have been 1, "true", etc. and make it just plain true.
The code could have been written:
var context = document.createElement('canvas').getContext;
var contextDoesNotExist = !context;
var contextExists = !contextDoesNotExist;
return contextExists;
Using !!variable gives you a guarantee of typecast to boolean.
To give you a simple example:
"" == false (is true)
"" === false (is false)
!!"" == false (is true)
!!"" === false (is true)
But it doesn't make sense to use if you are doing something like:
var a = ""; // or a = null; or a = undefined ...
if(!!a){
...
The if will cast it to boolean so there is no need to make the implicit double negative cast.
! casts "something"/"anything" to a boolean.
!! gives the original boolean value back (and guarantees the expression is a boolean now, regardless to what is was before)
The first ! coerces the variable to a boolean type and inverts it. The second ! inverts it again (giving you the original (correct) boolean value for whatever you are checking).
For clarity you would be better off using
return Boolean(....);
document.createElement('canvas').getContext may evaluate to either undefined or an object reference. !undefined yields true, ![some_object] yields false. This is almost what we need, just inverted. So !! serves to convert undefined to false and an object reference to true.
It's to do with JavaScript's weak typing. document.createElement('canvas').getContext is a function object. By prepending a single ! it evaluates it as a boolean expression and flips the answer around. By prepending another !, it flips the answer back. The end result is that the function evaluates it as a boolean expression, but returns an actual boolean result rather than the function object itself. Prepending !! is a quick and dirty way to typecast an expression to a boolean type.
If document.createElement('canvas').getContext isn't undefined or null, it will return true. Otherwise it will return false.

Categories