Javascript setter returns value without validation - javascript

JavaScript setter updates the internal value at the reference but the return value is not correct.
var Game =
{
get points() {
return this._points;
},
set points(x){
x = Math.min(x,25);
this._points = x;
return this._points;
}
};
Game.points = 10 ;
console.log(Game.points); // outputs 10
var updatedPoints = (Game.points = 60);
console.log(updatedPoints); // outputs 60
console.log(Game.points); // outputs 25
Expected value for 'updatedPoints' was 25 !
Any idea why this could be happening ? Can you suggest if there is a way to fix this ?
Reason to fix this: To make sure the JS code performs as expected , maintainibility !

The JavaScript simple assignement (=) returns the right value as per the specification (11.13.1). This behavior ignores whatever validation happens in your setter.
From the spec:
The production AssignmentExpression : LeftHandSideExpression =
AssignmentExpression is evaluated as follows:
Let lref be the result of evaluating LeftHandSideExpression.
Let rref be the result of evaluating AssignmentExpression.
Let rval be GetValue(rref).
Throw a SyntaxError exception if the following conditions are all true:
Type(lref) is Reference is true
IsStrictReference(lref) is true
Type(GetBase(lref)) is Environment Record
GetReferencedName(lref) is either "eval" or "arguments"
Call PutValue(lref, rval).
Return rval.
So there is no way to "fix" your issue as it is by design. Checking Game.points should be enough.

Related

Assign result of block to a variable (gives SyntaxError)

If I open a Node REPL, and enter this code, I can see that it evaluates to 3:
$ node
> { let a = 1 + 2; a }
3
>
However, this code does not work:
const result = { let a = 1 + 2; a };
I get this error:
const result = { let a = 1 + 2; a };
^
SyntaxError: Unexpected identifier
What am I missing here? Am I correct in assuming that the block evaluates to the last expression within it, or is Node's REPL misleading me here?
As you've seen in the Node REPL, a block evaluates to a value, and that value is usually the value of the last statement in the block.
In ECMAScript 6.0, a BlockStatement is defined as follows (with subscripts omitted for simplicity):
BlockStatement:
Block
Block:
{ StatementList }
StatementList:
StatementListItem
StatementList StatementListItem
StatementListItem:
Statement
Declaration
Per section 13.2.13, Note 2, "The value of a StatementList is the value of the last value producing item in the StatementList." A Block is evaluated to the value of its StatementList, and a BlockStatement is evaluated to the value of its Block.
Thus, Node is correctly evaluating your BlockStatement to the value of the last value producing item, which is a. This is not a bug, nor is it specific to Node.
The reason you are getting an error is because you are trying to use a BlockStatement in a context where it is not allowed.
const result = { let a = 1 + 2; a }; is a LexicalDeclaration, which is defined as follows (again, with subscripts omitted):
LexicalDeclaration:
LetOrConst BindingList ;
LetOrConst :
let
const
BindingList:
LexicalBinding
BindingList , LexicalBinding
LexicalBinding:
BindingIdentifier Initializer
BindingPattern Initializer
We also need the definition of Initializer:
Initializer:
= AssignmentExpression
As you can see, the part of your lexical declaration after the equal sign requires an AssignmentExpression. If you look through the grammar for expressions, you will see that BlockStatement is not an AssignmentExpression.
As of ES6.0, there is no way to use a BlockStatement direcly as an AssignmentExpression. However, if you want to evaluate one to an expression, you can use eval:
> const result = eval("{ let a = 1 + 2; a }");
> result
3
I don't recommend doing this under ordinary circumstances, but it is helpful for seeing how ES6.0 does indeed evaluate blocks to values.
In js braces represent an object which expects key: value pairs. You can get the result like this;
const result = {a: 1 + 2};
console.log(result.a);

Is it bad to set backup values for attributes in your constructor if no values are passed in [duplicate]

I am debugging some JavaScript and can't explain what this || does:
function (title, msg) {
var title = title || 'Error';
var msg = msg || 'Error on Request';
}
Why is this guy using var title = title || 'ERROR'? I sometimes see it without a var declaration as well.
What is the double pipe operator (||)?
The double pipe operator (||) is the logical OR operator . In most languages it works the following way:
If the first value is false, it checks the second value. If that's true, it returns true and if the second value is false, it returns false.
If the first value is true, it always returns true, no matter what the second value is.
So basically it works like this function:
function or(x, y) {
if (x) {
return true;
} else if (y) {
return true;
} else {
return false;
}
}
If you still don't understand, look at this table:
| true false
------+---------------
true | true true
false | true false
In other words, it's only false when both values are false.
How is it different in JavaScript?
JavaScript is a bit different, because it's a loosely typed language. In this case it means that you can use || operator with values that are not booleans. Though it makes no sense, you can use this operator with for example a function and an object:
(function(){}) || {}
What happens there?
If values are not boolean, JavaScript makes implicit conversion to boolean. It means that if the value is falsey (e.g. 0, "", null, undefined (see also All falsey values in JavaScript)), it will be treated as false; otherwise it's treated as true.
So the above example should give true, because empty function is truthy. Well, it doesn't. It returns the empty function. That's because JavaScript's || operator doesn't work as I wrote at the beginning. It works the following way:
If the first value is falsey, it returns the second value.
If the first value is truthy, it returns the first value.
Surprised? Actually, it's "compatible" with the traditional || operator. It could be written as following function:
function or(x, y) {
if (x) {
return x;
} else {
return y;
}
}
If you pass a truthy value as x, it returns x, that is, a truthy value. So if you use it later in if clause:
(function(x, y) {
var eitherXorY = x || y;
if (eitherXorY) {
console.log("Either x or y is truthy.");
} else {
console.log("Neither x nor y is truthy");
}
}(true/*, undefined*/));
you get "Either x or y is truthy.".
If x was falsey, eitherXorY would be y. In this case you would get the "Either x or y is truthy." if y was truthy; otherwise you'd get "Neither x nor y is truthy".
The actual question
Now, when you know how || operator works, you can probably make out by yourself what does x = x || y mean. If x is truthy, x is assigned to x, so actually nothing happens; otherwise y is assigned to x. It is commonly used to define default parameters in functions. However, it is often considered a bad programming practice, because it prevents you from passing a falsey value (which is not necessarily undefined or null) as a parameter. Consider following example:
function badFunction(/* boolean */flagA) {
flagA = flagA || true;
console.log("flagA is set to " + (flagA ? "true" : "false"));
}
It looks valid at the first sight. However, what would happen if you passed false as flagA parameter (since it's boolean, i.e. can be true or false)? It would become true. In this example, there is no way to set flagA to false.
It would be a better idea to explicitly check whether flagA is undefined, like that:
function goodFunction(/* boolean */flagA) {
flagA = typeof flagA !== "undefined" ? flagA : true;
console.log("flagA is set to " + (flagA ? "true" : "false"));
}
Though it's longer, it always works and it's easier to understand.
You can also use the ES6 syntax for default function parameters, but note that it doesn't work in older browsers (like IE). If you want to support these browsers, you should transpile your code with Babel.
See also Logical Operators on MDN.
It means the title argument is optional. So if you call the method with no arguments it will use a default value of "Error".
It's shorthand for writing:
if (!title) {
title = "Error";
}
This kind of shorthand trick with boolean expressions is common in Perl too. With the expression:
a OR b
it evaluates to true if either a or b is true. So if a is true you don't need to check b at all. This is called short-circuit boolean evaluation so:
var title = title || "Error";
basically checks if title evaluates to false. If it does, it "returns" "Error", otherwise it returns title.
If title is not set, use 'ERROR' as default value.
More generic:
var foobar = foo || default;
Reads: Set foobar to foo or default.
You could even chain this up many times:
var foobar = foo || bar || something || 42;
Explaining this a little more...
The || operator is the logical-or operator. The result is true if the first part is true and it is true if the second part is true and it is true if both parts are true. For clarity, here it is in a table:
X | Y | X || Y
---+---+--------
F | F | F
---+---+--------
F | T | T
---+---+--------
T | F | T
---+---+--------
T | T | T
---+---+--------
Now notice something here? If X is true, the result is always true. So if we know that X is true we don't have to check Y at all. Many languages thus implement "short circuit" evaluators for logical-or (and logical-and coming from the other direction). They check the first element and if that's true they don't bother checking the second at all. The result (in logical terms) is the same, but in terms of execution there's potentially a huge difference if the second element is expensive to calculate.
So what does this have to do with your example?
var title = title || 'Error';
Let's look at that. The title element is passed in to your function. In JavaScript if you don't pass in a parameter, it defaults to a null value. Also in JavaScript if your variable is a null value it is considered to be false by the logical operators. So if this function is called with a title given, it is a non-false value and thus assigned to the local variable. If, however, it is not given a value, it is a null value and thus false. The logical-or operator then evaluates the second expression and returns 'Error' instead. So now the local variable is given the value 'Error'.
This works because of the implementation of logical expressions in JavaScript. It doesn't return a proper boolean value (true or false) but instead returns the value it was given under some rules as to what's considered equivalent to true and what's considered equivalent to false. Look up your JavaScript reference to learn what JavaScript considers to be true or false in boolean contexts.
|| is the boolean OR operator. As in JavaScript, undefined, null, 0, false are considered as falsy values.
It simply means
true || true = true
false || true = true
true || false = true
false || false = false
undefined || "value" = "value"
"value" || undefined = "value"
null || "value" = "value"
"value" || null = "value"
0 || "value" = "value"
"value" || 0 = "value"
false || "value" = "value"
"value" || false = "value"
Basically, it checks if the value before the || evaluates to true. If yes, it takes this value, and if not, it takes the value after the ||.
Values for which it will take the value after the || (as far as I remember):
undefined
false
0
'' (Null or Null string)
Whilst Cletus' answer is correct, I feel more detail should be added in regards to "evaluates to false" in JavaScript.
var title = title || 'Error';
var msg = msg || 'Error on Request';
Is not just checking if title/msg has been provided, but also if either of them are falsy. i.e. one of the following:
false.
0 (zero)
"" (empty string)
null.
undefined.
NaN (a special Number value meaning Not-a-Number!)
So in the line
var title = title || 'Error';
If title is truthy (i.e., not falsy, so title = "titleMessage" etc.) then the Boolean OR (||) operator has found one 'true' value, which means it evaluates to true, so it short-circuits and returns the true value (title).
If title is falsy (i.e. one of the list above), then the Boolean OR (||) operator has found a 'false' value, and now needs to evaluate the other part of the operator, 'Error', which evaluates to true, and is hence returned.
It would also seem (after some quick firebug console experimentation) if both sides of the operator evaluate to false, it returns the second 'falsy' operator.
i.e.
return ("" || undefined)
returns undefined, this is probably to allow you to use the behavior asked about in this question when trying to default title/message to "". i.e. after running
var foo = undefined
foo = foo || ""
foo would be set to ""
Double pipe stands for logical "OR". This is not really the case when the "parameter not set", since strictly in JavaScript if you have code like this:
function foo(par) {
}
Then calls
foo()
foo("")
foo(null)
foo(undefined)
foo(0)
are not equivalent.
Double pipe (||) will cast the first argument to Boolean and if the resulting Boolean is true - do the assignment, otherwise it will assign the right part.
This matters if you check for unset parameter.
Let's say, we have a function setSalary that has one optional parameter. If the user does not supply the parameter then the default value of 10 should be used.
If you do the check like this:
function setSalary(dollars) {
salary = dollars || 10
}
This will give an unexpected result for a call like:
setSalary(0)
It will still set the 10 following the flow described above.
Double pipe operator
This example may be useful:
var section = document.getElementById('special');
if(!section){
section = document.getElementById('main');
}
It can also be:
var section = document.getElementById('special') || document.getElementById('main');
To add some explanation to all said before me, I should give you some examples to understand logical concepts.
var name = false || "Mohsen"; # name equals to Mohsen
var family = true || "Alizadeh" # family equals to true
It means if the left side evaluated as a true statement it will be finished and the left side will be returned and assigned to the variable. in other cases the right side will be returned and assigned.
And operator have the opposite structure like below.
var name = false && "Mohsen" # name equals to false
var family = true && "Alizadeh" # family equals to Alizadeh
Quote: "What does the construct x = x || y mean?"
Assigning a default value.
This means providing a default value of y to x,
in case x is still waiting for its value but hasn't received it yet or was deliberately omitted in order to fall back to a default.
And I have to add one more thing: This bit of shorthand is an abomination. It misuses an accidental interpreter optimization (not bothering with the second operation if the first is truthy) to control an assignment. That use has nothing to do with the purpose of the operator. I do not believe it should ever be used.
I prefer the ternary operator for initialization, for example,
var title = title?title:'Error';
This uses a one-line conditional operation for its correct purpose. It still plays unsightly games with truthiness but, that's JavaScript for you.

Base class in javascript [duplicate]

I am debugging some JavaScript and can't explain what this || does:
function (title, msg) {
var title = title || 'Error';
var msg = msg || 'Error on Request';
}
Why is this guy using var title = title || 'ERROR'? I sometimes see it without a var declaration as well.
What is the double pipe operator (||)?
The double pipe operator (||) is the logical OR operator . In most languages it works the following way:
If the first value is false, it checks the second value. If that's true, it returns true and if the second value is false, it returns false.
If the first value is true, it always returns true, no matter what the second value is.
So basically it works like this function:
function or(x, y) {
if (x) {
return true;
} else if (y) {
return true;
} else {
return false;
}
}
If you still don't understand, look at this table:
| true false
------+---------------
true | true true
false | true false
In other words, it's only false when both values are false.
How is it different in JavaScript?
JavaScript is a bit different, because it's a loosely typed language. In this case it means that you can use || operator with values that are not booleans. Though it makes no sense, you can use this operator with for example a function and an object:
(function(){}) || {}
What happens there?
If values are not boolean, JavaScript makes implicit conversion to boolean. It means that if the value is falsey (e.g. 0, "", null, undefined (see also All falsey values in JavaScript)), it will be treated as false; otherwise it's treated as true.
So the above example should give true, because empty function is truthy. Well, it doesn't. It returns the empty function. That's because JavaScript's || operator doesn't work as I wrote at the beginning. It works the following way:
If the first value is falsey, it returns the second value.
If the first value is truthy, it returns the first value.
Surprised? Actually, it's "compatible" with the traditional || operator. It could be written as following function:
function or(x, y) {
if (x) {
return x;
} else {
return y;
}
}
If you pass a truthy value as x, it returns x, that is, a truthy value. So if you use it later in if clause:
(function(x, y) {
var eitherXorY = x || y;
if (eitherXorY) {
console.log("Either x or y is truthy.");
} else {
console.log("Neither x nor y is truthy");
}
}(true/*, undefined*/));
you get "Either x or y is truthy.".
If x was falsey, eitherXorY would be y. In this case you would get the "Either x or y is truthy." if y was truthy; otherwise you'd get "Neither x nor y is truthy".
The actual question
Now, when you know how || operator works, you can probably make out by yourself what does x = x || y mean. If x is truthy, x is assigned to x, so actually nothing happens; otherwise y is assigned to x. It is commonly used to define default parameters in functions. However, it is often considered a bad programming practice, because it prevents you from passing a falsey value (which is not necessarily undefined or null) as a parameter. Consider following example:
function badFunction(/* boolean */flagA) {
flagA = flagA || true;
console.log("flagA is set to " + (flagA ? "true" : "false"));
}
It looks valid at the first sight. However, what would happen if you passed false as flagA parameter (since it's boolean, i.e. can be true or false)? It would become true. In this example, there is no way to set flagA to false.
It would be a better idea to explicitly check whether flagA is undefined, like that:
function goodFunction(/* boolean */flagA) {
flagA = typeof flagA !== "undefined" ? flagA : true;
console.log("flagA is set to " + (flagA ? "true" : "false"));
}
Though it's longer, it always works and it's easier to understand.
You can also use the ES6 syntax for default function parameters, but note that it doesn't work in older browsers (like IE). If you want to support these browsers, you should transpile your code with Babel.
See also Logical Operators on MDN.
It means the title argument is optional. So if you call the method with no arguments it will use a default value of "Error".
It's shorthand for writing:
if (!title) {
title = "Error";
}
This kind of shorthand trick with boolean expressions is common in Perl too. With the expression:
a OR b
it evaluates to true if either a or b is true. So if a is true you don't need to check b at all. This is called short-circuit boolean evaluation so:
var title = title || "Error";
basically checks if title evaluates to false. If it does, it "returns" "Error", otherwise it returns title.
If title is not set, use 'ERROR' as default value.
More generic:
var foobar = foo || default;
Reads: Set foobar to foo or default.
You could even chain this up many times:
var foobar = foo || bar || something || 42;
Explaining this a little more...
The || operator is the logical-or operator. The result is true if the first part is true and it is true if the second part is true and it is true if both parts are true. For clarity, here it is in a table:
X | Y | X || Y
---+---+--------
F | F | F
---+---+--------
F | T | T
---+---+--------
T | F | T
---+---+--------
T | T | T
---+---+--------
Now notice something here? If X is true, the result is always true. So if we know that X is true we don't have to check Y at all. Many languages thus implement "short circuit" evaluators for logical-or (and logical-and coming from the other direction). They check the first element and if that's true they don't bother checking the second at all. The result (in logical terms) is the same, but in terms of execution there's potentially a huge difference if the second element is expensive to calculate.
So what does this have to do with your example?
var title = title || 'Error';
Let's look at that. The title element is passed in to your function. In JavaScript if you don't pass in a parameter, it defaults to a null value. Also in JavaScript if your variable is a null value it is considered to be false by the logical operators. So if this function is called with a title given, it is a non-false value and thus assigned to the local variable. If, however, it is not given a value, it is a null value and thus false. The logical-or operator then evaluates the second expression and returns 'Error' instead. So now the local variable is given the value 'Error'.
This works because of the implementation of logical expressions in JavaScript. It doesn't return a proper boolean value (true or false) but instead returns the value it was given under some rules as to what's considered equivalent to true and what's considered equivalent to false. Look up your JavaScript reference to learn what JavaScript considers to be true or false in boolean contexts.
|| is the boolean OR operator. As in JavaScript, undefined, null, 0, false are considered as falsy values.
It simply means
true || true = true
false || true = true
true || false = true
false || false = false
undefined || "value" = "value"
"value" || undefined = "value"
null || "value" = "value"
"value" || null = "value"
0 || "value" = "value"
"value" || 0 = "value"
false || "value" = "value"
"value" || false = "value"
Basically, it checks if the value before the || evaluates to true. If yes, it takes this value, and if not, it takes the value after the ||.
Values for which it will take the value after the || (as far as I remember):
undefined
false
0
'' (Null or Null string)
Whilst Cletus' answer is correct, I feel more detail should be added in regards to "evaluates to false" in JavaScript.
var title = title || 'Error';
var msg = msg || 'Error on Request';
Is not just checking if title/msg has been provided, but also if either of them are falsy. i.e. one of the following:
false.
0 (zero)
"" (empty string)
null.
undefined.
NaN (a special Number value meaning Not-a-Number!)
So in the line
var title = title || 'Error';
If title is truthy (i.e., not falsy, so title = "titleMessage" etc.) then the Boolean OR (||) operator has found one 'true' value, which means it evaluates to true, so it short-circuits and returns the true value (title).
If title is falsy (i.e. one of the list above), then the Boolean OR (||) operator has found a 'false' value, and now needs to evaluate the other part of the operator, 'Error', which evaluates to true, and is hence returned.
It would also seem (after some quick firebug console experimentation) if both sides of the operator evaluate to false, it returns the second 'falsy' operator.
i.e.
return ("" || undefined)
returns undefined, this is probably to allow you to use the behavior asked about in this question when trying to default title/message to "". i.e. after running
var foo = undefined
foo = foo || ""
foo would be set to ""
Double pipe stands for logical "OR". This is not really the case when the "parameter not set", since strictly in JavaScript if you have code like this:
function foo(par) {
}
Then calls
foo()
foo("")
foo(null)
foo(undefined)
foo(0)
are not equivalent.
Double pipe (||) will cast the first argument to Boolean and if the resulting Boolean is true - do the assignment, otherwise it will assign the right part.
This matters if you check for unset parameter.
Let's say, we have a function setSalary that has one optional parameter. If the user does not supply the parameter then the default value of 10 should be used.
If you do the check like this:
function setSalary(dollars) {
salary = dollars || 10
}
This will give an unexpected result for a call like:
setSalary(0)
It will still set the 10 following the flow described above.
Double pipe operator
This example may be useful:
var section = document.getElementById('special');
if(!section){
section = document.getElementById('main');
}
It can also be:
var section = document.getElementById('special') || document.getElementById('main');
To add some explanation to all said before me, I should give you some examples to understand logical concepts.
var name = false || "Mohsen"; # name equals to Mohsen
var family = true || "Alizadeh" # family equals to true
It means if the left side evaluated as a true statement it will be finished and the left side will be returned and assigned to the variable. in other cases the right side will be returned and assigned.
And operator have the opposite structure like below.
var name = false && "Mohsen" # name equals to false
var family = true && "Alizadeh" # family equals to Alizadeh
Quote: "What does the construct x = x || y mean?"
Assigning a default value.
This means providing a default value of y to x,
in case x is still waiting for its value but hasn't received it yet or was deliberately omitted in order to fall back to a default.
And I have to add one more thing: This bit of shorthand is an abomination. It misuses an accidental interpreter optimization (not bothering with the second operation if the first is truthy) to control an assignment. That use has nothing to do with the purpose of the operator. I do not believe it should ever be used.
I prefer the ternary operator for initialization, for example,
var title = title?title:'Error';
This uses a one-line conditional operation for its correct purpose. It still plays unsightly games with truthiness but, that's JavaScript for you.

Javascript Dictionary is returning both a value and "undefined" [duplicate]

I have already read the following SO posts:
Why does this JavaScript code print “undefined” on the console?
Why does Chrome & FireFox console print undefined?
Why does the JS console return an extra undefined?
But none of it explains why the JavaScript console prints undefined when I declare a variable as follows:
var a;
It prints the result of this expression - which is undefined. And yes, var a is a valid expression on its own.
Actually, you should rather be amused by why console prints undefined when you write var a = 3 or something like this. It also prints undefined if function anyFunctionName() {} statement is processed. In fact, all the var and function declaration (!) statements seem to be ignored if there's another statement with some 'real' result:
>>> var a = 3;
undefined
>>> var a = 3; a = 4;
4
>>> var a = 3; a = 4; var a = 5; function f() {};
4 // !!!
Now, I suppose the real reason behind is behaviour of eval statement, as described here:
Let result be the result of evaluating the program prog.
If result.type is normal and its completion value is a value V, then return the value V.
If result.type is normal and its completion value is empty, then return the value undefined.
So now the question is, what does var a = 4 statement return? Guess what: it's not 4.
The production VariableStatement : var VariableDeclarationList; is
evaluated as follows:
Evaluate VariableDeclarationList.
Return (normal, empty, empty).
Now the most interesting part: what happened in the last example, why 4 is the result? That's explained in this section:
The production Program : SourceElements is evaluated as follows:
Let result be the result of evaluating SourceElements.
[...]
The production SourceElements : SourceElements *SourceElement* is evaluated as follows:
Let headResult be the result of evaluating SourceElements.
If headResult is an abrupt completion, return headResult.
Let tailResult be result of evaluating SourceElement.
If tailResult.value is empty, let V = headResult.value, otherwise let V = > tailResult.value.
Return (tailResult.type, V, tailResult.target)
Both function f() {} and var a = 5 statements' return values were (normal, empty, empty). So the script ended up with giving out the result of the first statement (starting from the script's end, so technically it's the last one) that's not (normal, empty, empty). That is the result of a = 4 assignment statement - which is 4.
P.S. And now for some icing on the cake: consider the following:
>>> function f() {}
undefined
>>> (function f() {})
function f() {}
The difference is quite subtle: the first input is treated as a Function Declaration statement, which, according to this rule...
The production SourceElement : FunctionDeclaration is evaluated as
follows:
Return (normal, empty, empty).
... will eventually produce undefined when eval-ed, as we already know.
The second input, however, is treated as a Function Expression, which is evaluated to the function itself. That means it'll be passed through eval and eventually returned to the console (in its format).
var a=1;
a
gives:
1
while
var a=1;
gives:
undefined
in the first case the console evaluates a so it prints the value of a
in the second case the console does not evaluate the value of a, but it evaluates the expression itself.
because all you are doing is declaring there is a variable - what is it? a string, an integer, a boolean - we don't know yet - hence undefined
Each time you evaluate a line of code, you get a completion type/record result which has 3 attributes: type, value and target. According to the Ecma specification:
If result.type is normal and its completion value is a value V, then return the value V.
If result.type is normal and its completion value is empty, then return the value undefined.
It turns out that when you declare a variable or a function, the completion type is (normal,empty,empty). Since the result.type is normal and value is empty, it returns the value undefined.
However when you type a = 3, it's an assignment expression and its completion type is (normal, GetValue(), empty). So you will just see 3 in the console.
For terms around statement and expression, see difference statement/expression.
For different values of completion type, see completion type documentation.
If you check the completion type documentation, you can see that empty statement ; has also a completion type (normal, empty, empty) (so it should return undefined), and indeed it's the case. For the same reason, if (x>3) {console.log(x)} also returns undefined and do {console.log(3);} while (false) too.
However, (function f(){}) doesn't return undefined because it's an expression statement.
Test by yourself. Here are some more examples:
eval('function f(){}'); // Return (normal, empty, empty), undefined
eval(';'); // Return (normal, empty, empty), undefined
eval('(function f(){})'); // (normal, GetValue(exprRef), empty), ExpresionStatement
function foo() {
return 4;
} // Return (normal, empty, empty), undefined
foo(); // (return, 4, empty), 4
eval('function foo() {return 5;}'); // Return (normal, empty, empty), undefined
eval('foo();'); // (return, 4, empty), 4
let x = 4; // (normal, empty, empty), undefined
if (x > 3) {
console.log(x);
} // (normal, empty, empty), undefined
console.log(6); // (normal, empty, empty), undefined
eval('let x = 4; if (x>3) {console.log(x)}'); // undefined
let y = 5; // (normal, empty, empty), undefined
do {
console.log(3);
y++;
} while (y < 8); // this returns y, can you explain why?
do {
console.log(3);
} while (false); // undefined since (normal, empty, empty)

Javascript shorthand if-else and returning

Can the javascript shorthand for if-else return out of a function? If so how would this work.
eg.
I have this:
if(boolean){
return;
}
and I would like to write it as this:
(value)? return;
Chrome complains that return is unexpected. Is there anyway to write something like this so that it is valid?
No, you can't do that unless you return a value. For example if your function had to return a value you could have written:
return boolean ? 'foo' : 'bar';
But you cannot stop the execution of the function by returning void using the conditional operator.
If you intend to return from the function at this point in its execution regardless of whether the test evaluates true or false, you can use,
return (value) ? 1 : 2;
But if you merely wish to return early when a test evaluates true (for instance, as a sanity-check to prevent execution when parameters are invalid), the shortest you can make it is:
if (boolean) return;
if(boolean) return;
Single line , readable , perfectly valid;
I know it's an old question but I want to add that there is a non-standard way to return out of a function in shorthand if-else, and that is performing Immediately Invoked Function Expression (IIFE):
function outOfFunction(boolean){
return (boolean)?(()=>{return true;})():(()=>{return false;})();
}
console.log(outOfFunction(true));
console.log(outOfFunction(false));
And if we want to be out of the function or continue with other task:
function shorthandExampleJustTrue(boolean){
var someVar = "I'm out";
return (boolean)?(()=>{return true;})():(()=>{
console.log("here my code ");
console.log(someVar);
return "anythig else";
})();
}
console.log(shorthandExampleJustTrue(true));
console.log(shorthandExampleJustTrue(false));
When we use arrow functions we are able to access to variables out of the immediate function context.
You want to do a ternary operator
which is this:
(bool) ? ifTrue : ifFalse;
Please note: you cannot omit the else portion of a ternary operator.
http://en.wikipedia.org/wiki/Ternary_operation
The conditional "ternary operator" (condition ? expression to evaluate when true : expression to evaluate when false) is often used for simple conditional variable assignment.
if you need :
if( x > 0) {
a = 10;
}else{
a = 30;
}
you can write:
a = (x>0)? 10 : 30;
You can think of it like a simple function, which takes 3 parameters (p1, p2, p3), if p1 is true it returns p2 and if p1 is false then it returns p3.
(p1)? p2 : p3;
And just like such a function, there's no way for it to cause the parent function to return based on the condition. It is not therefore a shorthand for if/else.
if I'm not mistaken you're talking about this right? a short-hand.
return (if the value here is true then ->) && false
example:
const isGood = true && "yeah";
console.log(isGood) //yeah
Use this as your short hand if the value is true then it will return false; using the && operator is better

Categories