In the below code how does passing bar as
function (n) { return n; }
to foo evaluate to true in the if block?
function foo(bar) {
if (bar) {
// true
} else {
// false
}
}
This has me puzzled so any help is much appreciated.
If bar is bound to an anonymous function, then it is an object. Objects are 'truthy' in JavaScript.
The only values in JavaScript that are 'falsy' are:
false
null
undefined
'' (empty string)
0 (zero as a number)
NaN
Everything else is 'truthy', including function objects.
If you meant to call the anonymous function, you'd do if (bar(5)) which would call your anonymous function with the argument 5. Then your anonymous function would return n (which is 5 in this case). As 5 is not a falsy object, this would go to the true branch as well. Doing if (bar(0)) would got to the else branch, because 0 is falsy.
Anything not null, 0, false, empty string or undefined is going to evaluate to true in an if(something) statement, this is just how weak-typing in JavaScript works.
If you want more specificity you may want to look at the typeof operator to check for the type you're expecting, or use a another stronger check like this:
if(bar === true) {
Using === checks for both value and type equivalence.
You could use typeof() if you want to know what type it returns
It always return true, because bar is not null. if an expression within an if statement is not a logic expression (e.g. if(x <7)) then performs a check for null. If it is null it returns false, otherwise true.
In your example you have defined bar as the function {returns n;} so that is why your if statement is evaluating to true.
If bar returns a bool (true or false) then you need to call the function and get the result, rather than passing a reference to the function - this is done using parentheses:
var exampleA = bar(false); // executes function bar and returns the result (false) in exampleA
var exampleB = bar; // stores a reference to the function bar in variable exampleB
Related
I'm trying to understand the below block of syntax (taken from angular docs to represent the use of angular noop as an 'empty' function)
function foo(callback) {
var result = calculateResult();
(callback || angular.noop)(result);
}
I don't understand the '||' syntax. I tried looking it up but had trouble searching and wasn't really sure what to search.
Thinking of it as 'OR' syntax, it would mean to me if a function was assigned to the callback or if the function was assigned to angular noop would equal true and then a function is being called on true. But obviously that's wrong
Apologies in advance for the newbishness of the question.
- EDIT -
To clarify further, I'm aware of what it does guessing from the example. However, I'm trying to figure out what javascripts rule say that would cause the return statement for (callback1 || callback2) to return a function object instead of a boolean (as implied by the fact that in the example you can call the return of the sub-expression).
This bit
(callback || angular.noop)(result);
is short for:
if (callback) {
callback(result);
} else {
angular.noop(result);
}
It takes advantage of the fact that || is lazily executed. The search term you're looking for is lazy evaluation. To explain the "why" on how this works, we can take a look at the ECMAScript specification, specifically 11.11 Binary Logical Operators,
The value produced by a && or || operator is not necessarily of type Boolean. The value produced will always be the value of one of the two operand expressions. Note that this doesn't mean that you can't depend on an expression such as:
if (a || b) // <-- logical expression will evaluate to the value of a or b, NOT true or false
because JavaScript evaluates boolean values as truthy or falsy, formally defined as the operation ToBoolean() in the ECMAScript specification.
From 9.2 ToBoolean
The abstract operation ToBoolean converts its argument to a value of type Boolean according to Table 11:
Argument
Type Result
Undefined false
Null false
Boolean The result equals the input argument (no conversion).
Number The result is false if the argument is +0, −0, or NaN;
otherwise the result is true.
String The result is false if the argument is the empty String
(its length is zero); otherwise the result is true.
Object True
Basically the statement
(callback || angular.noop)(result);
Can be read as:
Call the function callback or angular.noop with the argument of result
If callback is not defined the OR (||) will be evaluated to call the angular.noop function passing the variable result to the function.
The angular.noop() function is a function that does nothing. More read here https://docs.angularjs.org/api/ng/function/angular.noop
Let's say I have a variable myvar, and I don't have a variable myvar2. I can run the following without a problem:
typeof myvar
// ⇒ 'string'
typeof myvar2
// ⇒ 'undefined'
typeof and delete are the only functions I know of which don't throw errors when given an undefined parameter like this. I looked at the language spec for typeof and to my uninitiated eyes it seems to use internal functions like IsUnresolvableReference.
Edit: I'd been working in a language that checks type with a synonymous function, and hadn't noticed typeof is actually an operator in JavaScript. I've removed parentheses from the code here but left the above as written.
When I create a function:
function myFunc(input_variable) {
return("hello");
}
... as expected this throws a ReferenceError when passed myvar2 as a parameter, unless I run var myvar2;.
If I wrap the return in a try/catch statement to handle the myvar2 not defined case, I still get the same error, as the variable seems to be checked for a resolvable reference upon entry into the function (upon runtime?) :
function myFunc(input_var) {
try {
return "hello";
} catch(error) {
if (error.name === 'ReferenceError'){
return "world";
}
}
}
I was wondering how I can make a function that accepts unresolved references. My general guess is that, if it's a standard behaviour of functions, then perhaps I could modify some prototype for this construction specifically...? I'm aware prototypes are for objects, I'm wondering if this level of control over function is possible somehow?
By way of context, I always find myself writing function(input_var) :
if (typeof input_var == 'undefined' || my_settings.input_var_is_optional === true)
var input_var = 'Sometimes variables are optional. This is my default value.';
return dealWith(input_var);
} else if (typeof input_var == 'string') {
return dealWith(input_var);
} else {
// Already checked that input_var isn't optional, so we have a problem
return false; // or throw a TypeError or something like that
}
but the verbosity of all that plain puts me off writing type checking into my code, making it less robust to use functions more freely, or to pass onto other developers.
I'd like to write a type handling function, e.g.
For a function myFunc(input_var), if the variable passed in as parameter input_var has been defined, check if it's a string, else set it as "default_value". If it wasn't defined, also set it as "default_value", else it's a valid string, so just use input_var as is.
...but it's sabotaged by the fact that I can't actually pass anything in that's undefined, effectively stopping me from isolating this complexity in a separate function to which I could just pass 2 parameters: input_var (the real deal, not just its name), and expected_type.
function typeTest(input_var, expected_type) {
var is_optional_value = (typeof expected_type != 'undefined'
&& expected_type === true);
var optional_str = is_optional_value ? "|(undefined)" : ''
var type_test_regex = RegExp('^(?!' + expected_type + optional_str + '$)');
var is_expected_type = type_test_regex.test(typeof(input_var));
}
For example, to check that an optional variable passed into a function was both defined, and was defined as a string,
var myvar = 'abc'
// myvar2 is never defined
// Mandatory type (expecting a string):
typeTest(myvar, 'string'); // true
// if (/^(?!string)$)/.test(typeof(myvar))
typeTest(myvar2, 'string'); // throws error
// Mandatory type (expecting a number):
typeTest(myvar, 'number'); // false
typeTest(myvar2, 'number'); // throws error
// Optional type ("expected is true"):
typeTest(myvar, true); // true
// if (/^(?!string|(undefined)$)/.test(typeof(myvar))
typeTest(myvar2, true); // throws error
I was wondering how I can make a function that accepts unresolved references.
You can't. When you access an undeclared variable, the ReferenceError occurs before the function even gets called. There's nothing you can do inside the function to recover from this, because it hasn't even been called.
typeof and delete are the only functions I know of which don't throw errors when given an undefined parameter like this.
typeof and delete are not functions. That's why.
For example, to check that an optional variable passed into a function was both defined, and was defined as a string.
There's nothing stopping you from doing this. There is a difference between:
variables with the value undefined
parameters that have not been passed a value
undeclared variables.
There is no problem in dealing with the first two:
function hasType(val, type) {
return typeof val === type;
}
function myFunc(param1, param2) {
console.log('param1: ', hasType(param1, 'string'));
console.log('param2: ', hasType(param2, 'string'));
}
myFunc('hello');
There is no need to check whether someone is trying to call your functions with undeclared variables. If they are, then the problem is with their code and they need to fix it. If they are taking advantage of optional parameters, that is a different matter, and you can handle for that scenario just fine.
as the variable seems to be checked for a resolvable reference upon entry into the function
It is checked before entry.
Given foo(bar), the logic for resolution is "Get foo, then get bar, then call foo with the value of bar as an argument.
If bar isn't declared then you'll get a ReferenceError before the function is called in the first place.
typeof and delete are the only functions I know of which don't throw errors when given an undefined parameter like this.
From the documentation you link to:
The typeof Operator
The delete Operator
They aren't functions.
I was wondering how I can make a function that accepts unresolved references.
You can't.
For example, to check that an optional variable
If you want an argument to be optional then either:
Explicitly pass undefined:
typeTest(undefined, 'string');
Put the optional argument last in the arguments list:
typeTest('string');
Pass an object:
typeTest({ argument_name: 'string' });
You can using a function slide.
function attempt(f){
console.log(f());
}
attempt( function (){ return nomansland} );
//later an ajax call declares it:
var nomansland = "ok";
attempt( function (){ return nomansland} );
I'm trying to learn JavaScript by going through some code in an application and I keep seeing !variable in if conditions. For example:
if (!variable.onsubmit || (variable.onsubmit() != false)) {
What is it? Some kind of test if the variable is empty?
! is the logical not operator in JavaScript.
Formally
!expression is read as:
Take expression and evaluate it. In your case that's variable.onsubmit
Case the result of that evaluation and convert it to a boolean. In your case since onsubmit is likely a function, it means - if the function is null or undefined - return false, otherwise return true.
If that evaluation is true, return false. Otherwise return true.
In your case
In your case !variable.onsubmit means return true if there isn't a function defined (and thus is falsy), otherwise return false (since there is a function defined).
Simply put - !variable means take the truth value of variable and negate it.
Thus, if (!variable) { will enter the if clause if variable is false (or coerces to false)
In total
if (!variable.onsubmit || (variable.onsubmit() != false)) {
Means - check if variable.onsubmit is defined and truthy (thus true), then it checks if calling onsubmit returns a result that coerces to true. In a short line it checks if there is no onsubmit or it returns true.
Next time, how do I find this myself?
MDN has a list of operators here.
The language specification specifies such operators, though being the official specification it does contain some jargon which might be hard to understand.
It is a negation operator used for truth tests on a variable.
var myVariable = 1;
if ( ! myVariable )
{
// myVariable evaluates as false
}
if ( myVariable )
{
// myVariable evaluates as true
}
The selected answer already answers the question. One thing to add in this is that ! operator can be used in a rather interesting fashion.
obj = {}
if (!!obj) {console.log('works')} // !!obj = true
obj = undefined
if (!!obj) {console.log('does not work')} // !!obj = false
So double !! will change any expression to a boolean value with no exceptions.
This has a very peculiar use case in some cases.
Lets say there is a function that returns either true or false and nothing else. In that case one could just change return returnValue to return !!returnValue for extra caution (although not need in most of the cases)
Conversely, if a function only accepts true or false and nothing else, one could just call the function as functionA(!!parameter) instead of functionA(parameter), which again is not needed in most of the cases, but could ensure extra security
! is a logic reversal operator, if something was true it will change it to false, if something is false, it will change to true.
example, we know that empty string or 0 in boolean is false.
let a = Boolean("")
console.log(a) // shows false, because empty string in boolean is false
console.log(!a) // shows true, because logic is reversed
easier example:
let a = 5
let b = 1
let c = a > b
console.log(c) // shows true, since a,5 is bigger than b,1
console.log(!c) // shows false, since logic is now reversed
If I have a function
foo()
that I call with no arguments most of the time, but one argument in special cases, is
var arg1 = arguments[0];
if (arg1) {
<special case code>
}
inside the function a completely safe thing to do?
Yes it is safe. Unless you pass in false, "", 0, null or undefined as an argument. It's better to check againts the value of undefined. (If you pass in undefined then tough! that's not a valid argument).
There are 3 popular checks
foo === undefined : Standard check but someone (evil) might do window.undefined = true
typeof foo !== "undefined" : Checks for type and is safe.
foo === void 0 : void 0 returns the real undefined
But this is prefered
function myFunction(foo) {
if (foo !== undefined) {
...
} else {
...
}
}
Yes, that's fine. A reasonable alternative is to name the argument, and not use the arguments object:
function foo(specialArg)
{
if (specialArg)
{
// special case code
}
}
Note that if(bar) tests the truthiness of bar. If you call foo with any falsy value, such asfoo(0), foo(false), foo(null), etc., the special case code will not execute in the above function (or your original function, for that matter). You can change the test to
if (typeof specialArg !=== 'undefined')
{
// ...
}
to make sure that the special case code is executed when the argument is supplied but falsy.
You can do this:
function foo(arg1){
if (arg1){
// Special case
}
else{
// No argument
}
// Rest of function
}
As long as you document the behaviour sufficiently I don't see anything wrong with it.
However you'd be better off checking the argument length, as opposed to how you're doing it now. Say for example you called:
myFunction(0);
It will never process the argument.
If it's a single optional argument you may be better off having it as a named argument in the function and checking if a defined value was passed in, depends on your use case.
The basic fact you are interested in is "was foo called with 0 or 1 argument(s)?". So I would test arguments.length to avoid future problems with a special argument that evaluates to false.
What does this JS expression mean? What are we returning?
return dihy(year) in {353:1, 383:1};
This is a return statement that causes the containing function to return a Boolean value.
It calls the function dihy() with the value of the variable year as its argument.
It checks whether the return value is either 353 or 383 (the names of the properties that exist in the object literal). It does not matter what value the property has; it just needs to exist within the object. (That is, 1 is just an arbitrary value.)
If so, the function returns true, otherwise false.
JavaScript programmers sometimes use this approach because it is shorter than checking against each value individually, and it is easy to programmatically add new values to check against:
var foo = {353: 1, 383: 1};
function bar(year) {
return year in foo;
}
alert(bar(1955)); // false
foo[1955] = 1;
alert(bar(1955)); // true
You may want to look at the MDC documentation for the in operator.
It will be true if the call to the function dihy with the argument year is a key in the object {353:1, 383:1} and false otherwise.
It could be rewritten like this for example:
var result = dihy(year);
return result == 353 || result == 383;
This is an expression:
dihy(year) in {353:1, 383:1}
The dihy(year) function call presumably returns a Number value. If that value is either 353 or 383, the expression will evaluate to true, otherwise to false.
Note that your code is not an expression, but a statement, the return statement:
return expression;
So, the return statement will either return true or false.
Returns true or false, depending is the result that dihy() returns 353 or 383 (true for those two, anything else is false).
And it means exactly that... is the result of this function contained in this data collection...
There is no reason to use an object here, i.e. {353: 1, 383: 1}. In fact, the values of 1 are confusing and can make the uninitiated think that the value of 1 is being returned when it is not and is purely arbitrary.
The following is equivalent:
dihy(year) in [353, 383]