Is order of evaluation sequential in Javascript? - javascript

At a job interview, I was perplexed to hear "javascript can evaluate statements out of order." To what degree is this true? I can imagine a hundred ways to explicitly evaluate statements out of order -- such as in a time-sharing operating system. But he seemed to say that if I evaluate
console.log('a')
console.log('b')
that the Javascript spec somehow doesn't require that the output would be a first then b. I can imagine that the evaluator might try to evaluate the second statement if the IO of the first is blocking if the statements are functionally pure, i.e. no side effects, but side effects must always occur in sequence, correct? And of course IO is one big side effect.
To what extent can spec-compliant Javascript evaluate out of order? Or was this a case of miscommunication?

JavaScript is single threaded (web workers aside). Period. ECMA-262 Language Specification Edition 5.1 says nothing about out-of-order execution. In your simple example these two statements are guaranteed to be executed in the same order.
Moreover, single block of JavaScript code will never be interrupted by any other block of code, e.g. event handler. That's why long running blocks of code cause UI to freeze:
for(var i = 0; i < 1000000000; ++i) {
console.log(i);
}
It's guaranteed that the block of code above will never be interrupted or reordered. As long as the loop is running, all event handlers and timeouts wait for single thread. And of course, numbers will appear in correct order.
What might be executed out-of-order is an asynchronous timeout:
setTimeout(function() {
console.log('a');
}, 1);
setTimeout(function() {
console.log('b');
}, 1);
Here you might expect a to be printed first, but it's possible that JS engine will reorder these events. After all you schedule these calls to execute at almost the same point in time.

Clearly miscommunication.
The dude was maybe referring to JavaScript hoisting. You can read more about it here : http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting
Furthermore, you can learn more particularities of the language here: http://bonsaiden.github.com/JavaScript-Garden/

For the most part, yes. With two major exceptions (leaving aside the obvious "define a function, call the function" which effectively "goes back" to the function body):
1: Hoisting. var statements are hoisted, so if you write
alert(a);
var a = 123;
You get undefined, and not an error message. This is because it is hoisted to
var a;
alert(a);
a = 123;
Similarly, function definitions are hoisted too. If you write:
foo(123);
function foo(num) {alert(num);}
It will work, because the function is hoisted. However, this does NOT work if you wrote
foo(123);
foo = function(num) {alert(num);}
Because that's an assignment of an anonymous function, not a function definition.
2: Asynchronous functions.
A common mistake among beginners is to write this:
var a = new XMLHttpRequest();
a.open("GET","sompage.php",true);
a.onreadystatechange = function() {
if( a.readyState == 4 && a.status == 200) {
myvar = "Done!";
}
};
a.send();
alert(myvar);
They expect the alert to say Done!, but instead they get an inexplicable error about it not being defined. This is because the myvar = "Done!" hasn't been run yet, despite appearing earlier in the script.
See also this anecdote from Computer Stupidities:
An introductory programming student once asked me to look at his program and figure out why it was always churning out zeroes as the result of a simple computation. I looked at the program, and it was pretty obvious:
begin
readln("Number of Apples", apples);
readln("Number of Carrots", carrots);
readln("Price for 1 Apple", a_price);
readln("Price for 1 Carrot", c_price);
writeln("Total for Apples", a_total);
writeln("Total for Carrots", c_total);
writeln("Total", total);
total := a_total + c_total;
a_total := apples * a_price;
c_total := carrots + c_price;
end;
Me: "Well, your program can't print correct results before they're computed."
Him: "Huh? It's logical what the right solution is, and the computer should reorder the instructions the right way."

I think they tried to put you on your wrong foot. Javascript is sequensial. Otherwise functions where you calculate values won't work out. What can be true is that console.log activates an Async task which means it can be executed in a different order. Like an Ajax call, a Webworker, a timeout or an interval.
If you do the following it will result B than A, this is not a sequensial code because in code. A comes for B but B is executed first.
setTimeout(function(){
console.log("A")
}, 5);
console.log("B");

Related

Double Function Call or storing the Result as a variable?

Assume I have some function f(-) defined elsewhere. I use it twice in the following type of code:
if (f(-) satisfies some condition) {
do some stuff
if (f(-) satisfies some other condition) {
do some other stuff
}
}
When the code is run, is f(-) calculated twice (or is the interpreter "intelligent" enough to see that it is enough to calculate it once)? If so, is it recommended to define a constant x = f(-) before that code and use that instead of f(-)? Usually I do this, but I am not fully sure if it is necessary, in particular, when f(-) can be computed really fast.
In case it matters, the language is JavaScript.
if (f(-) satisfies some other condition) will call the same function and it may never enter the block followed by this if, since the function satisfies the outer if that is why it entered into that block.
Create a const and depending on that value execute next step
const isFunResult = f(-);
// expecting this function gives a boolean
if(isFunResult){
// code goes here
}
else{
// code goes here
}
You can also use switch statement if function return multiple result .
In short words, the interpreter is not "intelligent" enough to see that it is enough to calculate it once. So it will call the function twice.
What you are looking for is something called memoization which is used to optimize performance for computational heavy functions to be remembered when the same parameters are passed.
If you need memoization, you could either implement that yourself in your own functions or you could use a javascript framework that supports that. Like React has the useMemo hook.
See https://reactjs.org/docs/hooks-reference.html#usememo
Usually you wont need that and just storing the result of the function in a variable will be enough for most use cases.
Run this to see the examples. Even if the conditions are the same.
function test_me() {
console.log("I got called");
return 99;
}
if (test_me() == 99) console.log("n=99"); // 1st function call
if (test_me() == 99) console.log("n=99"); // 2nd function call
// is different from the following
var n = test_me(); // function called once
if (n == 99) console.log("n=99"); // 1st test
if (n == 99) console.log("n=99"); // 1st test
To answer your question: Yes, it calculates function f(-) TWICE.
More than it is the intelligence of the interpreter, it is the intent of the programmer. The same function can be called twice if the programmer thinks that the function might return a changed value the second time. i.e: if the function uses a new Date() inside the function...
But, if the programmer knows that it is the same output both times (as in your case), it is better to define a constant x = f(-) and reuse it. This will improve performance (if the function is heavy), and improves code maintainability.
Even if it is a compiler, the compiler might not be intelligent enough to detect this, unless the function is a very simple code. But as #perellorodrigo mentioned, you can use memoization, but it is beyond the scope of this answer.
To wrap up, if you call the same function twice, it will be evaluated twice.

Javascript recursive function inside a for loop

var f_drum_min = function myself(a){
alert(a);
$f_min_node.push(a);
for (i=0;i<=$m;i++){
if ($f_leg[i][1]==a){
myself($f_leg[i][0]);
}
}
};
myself($f_leg[i][0]); breaks the for loop , how can I make it run multiple times in loop?
Your function is riddled with bad habits
There's no way for me to improve this function because I have no idea what all of those external states do. Nor is it immediately apparent what their data types are.
These are bad habits because there's no possible way to know the effect of your function. Its only input is a, yet the function depends on $f_min_node, $f_leg, and $m.
What is the value of those variables at the time you call your function?
What other functions change those values?
I assigned $f_min_node to some value and then called f_drum_min. How was I supposed to know that $f_min_node was going to get changed?
Every time you call your function, it's a big surprise what happens as a result. These are the woes of writing non-deterministic ("impure") functions.
Until you can fix these problems, recursion in a for-loop the least of your concerns
I have annotated your code with comments here
// bad function naming. what??
var f_drum_min = function myself(a){
// side effect
alert(a);
// external state: $f_min_node
// mutation: $f_min_node
$f_min_node.push(a);
// leaked global: i
// external state: $m
for (i=0;i<=$m;i++){
// external state: $f_leg
// loose equality operator: ==
if ($f_leg[i][1]==a){
myself($f_leg[i][0]);
}
}
};
I can help you write a deterministic recursive function that uses a linear iterative process though. Most importantly, it doesn't depend on any external state and it never mutates an input.
// Number -> Number
var fibonacci = function(n) {
function iter(i, a, b) {
if (i === 0)
return a;
else
return iter(i-1, b, a+b);
}
return iter(n, 0, 1);
}
fibonacci(6); // 8
for loops are pretty primitive; Imperative programmers will reach for it almost immediately thinking it's the only way to solve an iteration problem.
I could've used a for loop in this function, but thinking about the problem in a different way allows me to express it differently and avoid the for loop altogether.
One basic problem with the code, which would cause it to break under almost any circumstances, is that the loop variable i is a global, and is thus shared by all recursive invocations of the function.
For example, let's say the function is invoked for the first time. i is 0. Now it recurses, and let's say that the condition in the if is never true. At the end of the 2nd call, i = $m + 1. When you return to the first call, because i is global, the loop in the first call ends. I assume this is not what you want.
The fix for this is to declare i as local:
for (var i=0;i<=$m;i++){
This may or may not fix all of your problems (as pointed out in comments, we'd have to see more of your code to identify all possible issues), but it is a critical first step.

What is the JavaScript convention for no operation?

What is the JavaScript convention for no operation? Like a Python pass command.
One option is simply an empty function: function() {}
jQuery offers $.noop(), which simply calls the empty function above.
Is it acceptable to simply enter a value of false or 0?
In context... all of these work without throwing an error in Chrome:
var a = 2;
(a === 1) ? alert(1) : function() {};
(a === 1) ? alert(1) : $.noop();
(a === 1) ? alert(1) : false;
(a === 1) ? alert(1) : 0;
EDIT: A lot of people responded with, "don't do this! Change the code structure!" This reminds me of a post where someone asked how to sniff the browser. He received a barrage of posts saying, "DON'T DO THAT! IT'S EVIL," but nobody told him how to sniff the browser. This is not a code review. Imagine that you are dealing with legacy code that can't be changed, and without some function passed in, it will toss an error. Or, simply, that's the way the customer wants it, and they're paying me. So, respectfully, please answer the question: What is the best way to specify a "no operation" function in JavaScript?
EDIT2: How about one of these?
true;
false;
0;
1;
null;
To answer the original question, the most elegant and neat implementation of a noop function in pure Javascript (as is also discussed here) is Function.prototype. This is because:
Function.prototype is a function:
typeof Function.prototype === "function" // returns true
It can be invoked as a function and essentially does nothing as shown here:
setTimeout(function() {
console.log('Start: ', Date.now());
Function.prototype();
console.log('End : ', Date.now());
}, 1000);
Although this is a "true noop" since most browsers seem to do nothing to execute the noop defined this way (and hence save CPU cycles), there might be some performance issues associated with this (as is also mentioned by others in comments or in other answers).
However, that being said, you can easily define your own noop function and, infact, many libraries and frameworks also provide noop functions. Below are some examples:
var noop = function () {}; // Define your own noop in ES3 or ES5
const noop = () => {}; // Define in ES6 as Lambda (arrow function)
setTimeout(noop, 10000); // Using the predefined noop
setTimeout(function () {} , 10000); // Using directly in ES3 or ES5
setTimeout(() => {} , 10000); // Using directly in ES6 as Lambda (arrow function)
setTimeout(angular.noop, 10000); // Using with AngularJS 1.x
setTimeout(jQuery.noop, 10000); // Using with jQuery
Here is an alphabetical list of various implementations of noop functions (or related discussions or google searches):
AngularJS 1.x, Angular 2+ (Does not seem to have a native
implementation - use your own as shown above), Ember, jQuery, Lodash, NodeJS, Ramda, React (Does not seem to have a native implementation - use your own as shown above), RxJS,
Underscore
BOTTOM LINE: Although Function.prototype is an elegant way of expressing a noop in Javascript, however, there might be some performance issues related to its use. So, you can define and use your own (as shown above) or use one defined by the library/framework that you might be using in your code.
The most concise and performant noop is an empty arrow function: ()=>{}.
Arrow functions work natively in all browsers except IE (there is a babel transform if you must):
()=>{} vs. Function.Prototype
()=>{} is 87% faster than Function.prototype in Chrome 67.
()=>{} is 25% faster than Function.prototype in Firefox 60.
()=>{} is 85% faster than Function.prototype in Edge (6/15/2018).
()=>{} is 65% less code than Function.prototype.
The test below heats up using the arrow function to give bias to Function.prototype, yet the arrow function is the clear winner:
const noop = ()=>{};
const noopProto = Function.prototype;
function test (_noop, iterations) {
const before = performance.now();
for(let i = 0; i < iterations; i++) _noop();
const after = performance.now();
const elapsed = after - before;
console.info(`${elapsed.toFixed(4)}MS\t${_noop.toString().replace('\n', '')}\tISNOOP? ${_noop() === undefined}`);
return elapsed;
}
const iterations = 10000000
console.info(`noop time for ${iterations.toLocaleString()} iterations`)
const timings = {
noop: test(noop, iterations),
noopProto: test(noopProto, iterations)
}
const percentFaster = ((timings.noopProto - timings.noop)/timings.noopProto).toLocaleString("en-us", { style: "percent" });
console.info(`()=>{} is ${percentFaster} faster than Function.prototype in the current browser!`)
whatever you tend to achieve here is wrong. Ternary expressions shall not be used as a full statement, only in expression, so the answer to your question is:
none of your suggestions, instead do:
var a = 2;
if (a === 1)
alert(1)
// else do nothing!
then the code is easily understandable, readable and as much efficient as it can get.
Why make it more difficult, when it can be simple?
edit:
So then, does a "no-operation" command basically indicate an inferior code structure?
You're missing my point. All the above is about the ternary expression x ? y : z.
But, a no operation command does not makes sense in higher level languages such as Javascript.
It is usually used, in lower level languages such as assembly or C, as a way to make the processor do nothing for one instruction for timing purposes.
In JS, whether you do 0;, null;, function () {}; or an empty statement, there are great chances that it will be ignored by the interpretor when it is reading it, but before it gets interpreted, so in the end, you'll just make your program be loaded more slowly by a really tiny amount of time. Nota Bene: I'm assuming this, as I'm not involved in any widely used JS interpreter, and there are chances each interpreter has its own strategy.
In case you use something a bit more complicated, like $.noop() or var foo = function () {}; foo(), then the interpreter may do an unuseful function call that will end up spoiling a few bytes of your function stack, and a few cycles.
The only reason I see a function such as $.noop() would exist, would be to be able to still give a callback function to some event function that would throw an exception if it can't call that callback. But then, it's necessarily a function you need to give, and giving it the noop name is a good idea so you're telling your readers (and that may be you in 6 months) that you purposely give an empty function.
In the end, there's no such thing as "inferior" or "superior" code structure. You're either right or wrong in the way you use your tools.. Using a ternary for your example is like using a hammer when you want to screw. It'll work, but you're not sure you can hang something on that screw.
What could be considered either "inferior" or "superior" is the algorithm and ideas you put in your code. But that's another thing.
There is absolutely no problem or performance penalty of using Function.prototype over () => {}.
The main benefit of Function.prototype is having a singleton function rather than re-defining a new anonymous function each time. It's especially important to use a no-op like Function.prototype when defining default values and memoizing as it gives you a consistent object pointer which never changes.
The reason I'm recommending Function.prototype rather than Function is because of they're not the same:
Function() === Function()
// false
Function.prototype() === Function.prototype()
// true
Also, benchmarks from other answers are misleading. In fact, Function.prototype performs faster than () => {} depending on how you write and run the benchmark:
You can’t trust JS benchmarks << Specifically calling out benchmarks on this question.
Don't style your code from benchmarks; do whatever's maintainable and let the interpreter figure out how to optimize in the long run.
I think jQuery noop() is mostly intended to prevent code from crashing by providing a default function when the requested one is not available. For example, considering the following code sample, $.noop is chosen if fakeFunction is not defined, preventing the next call to fn from crashing:
var fn = fakeFunction || $.noop;
fn() // no crash
Then, noop() allows to save memory by avoiding to write the same empty function multiple times everywhere in your code. By the way, $.noop is a bit shorter than function(){} (6 bytes saved per token). So, there is no relationship between your code and the empty function pattern. Use null, false or 0 if you like, in your case there will be no side effect. Furthermore, it's worth noting that this code...
true/false ? alert('boo') : function(){};
... is completely useless since you'll never call the function, and this one...
true/false ? alert('boo') : $.noop();
... is even more useless since you call an empty function, which is exactly the same as...
true/false ? alert('boo') : undefined;
Let's replace the ternary expression with an if statement to see how much it's useless:
if (true/false) {
alert('boo');
} else {
$.noop(); // returns undefined which goes nowhere
}
You could simply write:
if (true/false) alert('boo');
Or even shorter:
true/false && alert('boo');
To finally answer your question, I guess a "conventional no operation" is the one which is never written.
I use:
(0); // nop
To test execution time of this run as:
console.time("mark");
(0); // nop
console.timeEnd("mark");
result: mark: 0.000ms
Using Boolean( 10 > 9) can be reduced it to simply ( 10 > 9) which returns true. Coming up with the idea to use a single operand I fully expected (0); would return false, but it simply returns the argument back as can be reviewed by performing this test at the console.
> var a = (0);
< undefined
> a
< 0
Need a succinct way of conditionally executing an expression, including function calls? (No noop necessary.)
true && expression // or `expression()`
Need a valid, callable expression with no side effects?
const noop = () => {}
if (true) noop()
Need a valid, non-callable expression with no side effects?
void 0;
false;
0;

javascript node.js in a stand-alone script, block/wait on a promise

I have a simple program in node.js, such as:
// CODE1
step1();
step2();
var o = step3();
step4(o);
step5();
step6();
this program is meant to be run in a stand-alone script (not in a web browser),
and it is a sequential program where order of execution is important (eg, step6 needs to be executed after step5).
the problem is that step3() is an async function, and the value 'o' is actually passed to a given callback,
so I would need to modify the program as follows:
// CODE2
step1();
step2();
step3( function (o) {
step4(o);
step5();
step6();
})
it could make sense to call step4 from the callback function, because it depends on the 'o' value computed by step3.
But step5 and step6 functions do not depend on 'o', and I have to include them in that callback function only to preserve the order of execution: step3, then step4, then step5 then step6.
this sounds really bad to me.
this is a sequential program, and so I would like to convert step3 to a sync function.
how to do this?
I am looking for something like this (eg using Q):
// CODE3
step1();
step2();
var deferred = Q.defer();
step3(deferred.resolve);
deferred.blockUntilFulfilled() // this function does not exist; this is what i am looking for
var o = deferred.inspect().value
step4(o);
step5();
step6();
How to do this?
ps: there are advantages and disadvantages of using sync or async, and this is a very interesting discussion. however, it is not the purpose of this question. in this question, i am asking how can i block/wait until a promise (or equivalent) gets fulfilled. Please, please, please, do not start a discussion on whether sync/blocking is good or not.
It's impossible to turn an async operation into a sync operation in vanilla JavaScript. There are things like node-fibers (a C++ add-on) that will allow this, or various compile-to-JS languages that will make the async operations look sync (essentially by rewriting your first code block to the second), but it is not possible to block until an async operation completes.
One way to see this is to note that the JavaScript event loop is always "run to completion," meaning that if you have a series of statements, they will always be guaranteed to execute one after the other, with nothing in between. Thus there is no way for an outside piece of information to come in and tell the code to stop blocking. Say you tried to make it work like so:
stepA();
stepB();
while (global.operationIsStillGoing) {
// do nothing
}
stepC();
This will never work, because due to the run-to-completion nature of JavaScript, it is not possible for anything to update global.operationIsStillGoing during the while loop, since that series of statements has not yet run to completion.
Of course, if someone writes a C++ addon that modifies the language, they can get around this. But that's not really JavaScript any more, at least in the commonly understood sense of ECMAScript + the event loop architecture.

Which of these cross-browser Javascript functions performs better?

As a rule of thumb, which of these methods of writing cross-browser Javascript functions will perform better?
Method 1
function MyFunction()
{
if (document.browserSpecificProperty)
doSomethingWith(document.browserSpecificProperty);
else
doSomethingWith(document.someOtherProperty);
}
Method 2
var MyFunction;
if(document.browserSpecificProperty) {
MyFunction = function() {
doSomethingWith(document.browserSpecificProperty);
};
} else {
MyFunction = function() {
doSomethingWith(document.someOtherProperty);
};
}
Edit: Upvote for all the fine answers so far. I've fixed the function to a more correct syntax.
Couple of points about the answers so far - whilst in the majority of cases it is a fairly pointless performance enhancement, there are a few reasons one might want to still spend some time analyzing the code:
Has to run on
slow computers, mobile devices, old
browsers etc.
Curiosity
Use the same
general principal to performance
enhance other scenarios where the
evaluation of the IF statement does
take some time.
Unless you're doing this a trillion times, it doesn't matter. Go with the one that is more readable and maintainable to you and/or your organization. The productivity gains you will get from writing clean, simple code matters way more than shaving a tenth of a microsecond off your JS execution time.
You should only even start thinking about what performs better when and only when you've written code and it is unacceptably slow. Then you should start tracking down the bottleneck, which will never be something like this. You will never get a measurable performance gain out of switching from one to the other here.
Unfortunately the code above is not actually cross-browser friendly as it relies on a mozilla quirk not present in other browsers -- namely that function statements are treated as function expressions inside branches. On browsers other that aren't built on mozilla the above code will always use the second function definition. I made a simple testcase to demonstrate this here.
Basically the ECMAScript spec says that function statements are treated similarly to var declarations, eg. they all get hoisted to the top of the current execution scope (eg. the start of a <script> tag, the start of a function, or the start of an eval block).
To clarify olliej's answer, your second method is technically a syntax error. You could rewrite it this way:
var MyFunction;
if(document.browserSpecificProperty) {
MyFunction = function() {
doSomethingWith(document.browserSpecificProperty);
};
} else {
MyFunction = function() {
doSomethingWith(document.someOtherProperty);
};
}
Which is at least correct syntax, but note that MyFunction would only be available in the scope in which that occurs. (Omit var MyFunction;, and preferably use window.MyFunction = function() ... for global.)
Technically, I would say that the second one would perform better, because the if statement is only executed once, rather than every time the function is run.
The difference, however, would be negligible to the point of being meaningless. The performance penalty of a single if statement such as this would be insignificant even compared to the performance penalty of simply calling a function. It would make a smallish difference even if if is called a million times.
The first one is easier to understand, because it doesn't have the awkwardness of defining the same function twice based on a condition, with both versions behaving differently. That seems to be a recipe for confusion later on.
I wouldn't be the first person to say that unless you are really insane about this optimization thing, you'll get more of a win out of code readability.
I generally prefer the second version, as the condition only has to be evaluated once and not on every call, but there are times when it's not really feasible because it will hamper readability.
Btw, this is a case where you might want to use the ?: operator, e.g (taken from production code):
var addEvent =
document.addEventListener ? function(type, listener) {
document.addEventListener(type, listener, false);
} :
document.attachEvent ? function(type, listener) {
document.attachEvent('on' + type, listener);
} :
throwError;
For your simplified example I would do what's below assuming that your browser property check only needs to be done once:
var MyFunction = (function() {
var rightProperty = document.browserSpecificProperty || document.someOtherProperty;
return function doSomethingWith() {
// use the rightProperty variable in your function
}
})();
The performance should be nearly equal!
Thing about using Frameworks like JQuery to get rid of the Browser compability problems!
If performance is your main goal, have a look at SlickSpeed! It is a page which benchmarks different JavaScript frameworks!

Categories

Resources