Why does Closure Compiler not shorten this? - javascript

I'm not sure whether this is just a bug or an intended feature.
Basically, I have this tiny function (I now see end is colored blue here but this works just fine, if I rename it to something else I still have the issue):
function f(a, b) {
var start = Math.min(a, b);
var end = Math.max(a, b);
tb.selectionStart = start;
tb.selectionEnd = end;
};
When closure-compiling it, I get:
function f(a,b){var c=Math.max(a,b);tb.selectionStart=Math.min(a,b);tb.selectionEnd=c};
However, why is selectionStart set to Math.min directly, whilst selecitonEnd is set to a variable (c), which is declared first? Isn't it shorter to do tb.selectionEnd=Math.max(a,b)?
Any ideas are appreciated.

EDIT: THERE IS AN "OFFICIAL" ANSWER IN THIS LINK:
https://web.archive.org/web/20151226143155/http://code.google.com/p/closure-compiler/issues/detail?id=410
I think an assignment to a variable, followed immediately by usage of that variable, can be inlined. However, if there is any statement in between that cannot be proven to be free of side-effects, then the compiler won't inline it.
In your case, assignment to variable "start" is separated from the usage of "start" only by the assignment statement to "end". However, this statement is free of side-effects since Math.max is an internal function and the compiler knows that it is side-effect-free.
However, in your case, assignment to variable "end" is separated from the usage of that variable by a statement, which is an assignment of "start" to a property. Now, I believe that the compiler does not assume that merely assigning to a property is always side-effect-free; that is because some properties, when assigned, actually cause different behavior, or change global state (such as RegExp). In some systems, property assignments actually trigger certain system-specific features (e.g. hardware interface) that may in-turn contain side-effects.
That is why, sometimes, when you have code like this:
foo.bar = 1;
foo.bar = 2;
foo.bar = 3;
The compiler won't eliminate the first two statements since assignment to "bar" may have side effects.
So, in your question, the variable "end" cannot be inlined because the statement tb.selectionStart = start; may have side effects (perhaps only in wierd cases).
If you make "tb" a local variable, or something that the compiler has complete control of (e.g. a simple object: var tb = {};), then you'll find that the compiler inlines all of the assignments just fine.

if you paste this code, this works.
function f(a, b) {
var start = Math.min(a, b);
tb.selectionStart = start;
var end = Math.max(a, b);
tb.selectionEnd = end;
};
function f(a,b){tb.selectionStart=Math.min(a,b);tb.selectionEnd=Math.max(a,b)};
i this is a mistake by closure compiler.

Related

javascript debugging: Is there a way to break on assignment of a specific value (to any variable)?

Similar in some sense to this question, but rather than waiting for any change in a particular variable, this would be by value: breaking on a particular primitive value (probably only particularly useful for numbers and strings) being assigned.
e.g. When watching for assignment of value 'asdf' (in some browser's dev tools or something like Firebug):
function example(){
var x = 'as';
x += 'df'; /*break here*/
return x;
}
y= example(); /*break here, as well*/
I suspect that the answer is that this doesn't exist (searching has turned up nothing), but just in case, I thought I'd ask.

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;

Check if a Javascript variable is used in any if statement

I want to check whether a given Javascript variable goes is used by any IF statements inside the program. Is there a way to dynamically do this rather than pure static code analysis.
Am not reading any file here. Lets say that I can inject a piece of JS code using some extension during run time and dynamically find if a given variable goes through an IF statement.
This is a bad idea. There are lots of things that could go wrong. You could look into sandboxing.
But, as long as you aren't relying on this for security, you might find this useful:
var x = function (a, b, c) { if(a) {console.log(a)}};
var y = function (a, b, c) { if(b) {console.log(a)}};
// You can get the text of a function. Notice it's been formatted.
console.log(x.toString());
>>> "function (a, b, c) { if (a) { console.log(a) } }"
var matcher = /if ?\(.?a.?\)/g;
x.toString().match(matcher);
>>> ["if (a)"]
y.toString().match(matcher);
>>> null
Things to be careful of, off the top of my head:
Different browsers may format the code differently.
Variables can be aliased by assigning them to a different name.
Variables can be accessed by index-access and strings.
This is a naïve regular expression and will obviously match if (nota).
Your javascript will be visible, so anyone who wants to get round this will find a way.

All possible ways to declare Javascript variables

To create an IDE that would autocomplete all variables the user declares but would be oblivious to other variables such as Math.PI or even the module Math, the IDE would need to be able to identify all identifiers relating to variables declared by the user. What mechanism could be used to capture all such variables, assuming you already have access to the AST (Abstract Symbol Table) for the program?
I am using reflect.js (https://github.com/zaach/reflect.js) to generate the AST.
I think it's pretty much impossible
Here is why I think it's pretty much impossible without executing it:
Let us go through the unexplored parts, from easy to hard.
Easy to catch:
Function scope is missed here:
(function(x){
//x is now an object with an a property equal to 3
// for the scope of that IIFE.
x;
})({a:3});
Here is some fun dirty tricks for you all.:
Introducing... drum roll... Block Scoping!!
with({x:3}){
x;//x is now declared in the scope of that with and is equal to 3.
}
try{ throw 5}catch(x){
x // x is now declared in the scope of the try block and is equal to 5;
}
(people reading: I beg you to please not use these last two for actual scoping in code :))
Not easy:
Bracket notation:
var n = "lo";
a["h"+"e"+"l"+n] = "world"; // need to understand that a.hello is a property.
// not a part of the ast!
The really hard parts:
Let us not forget invoking the compiler These would not show up in the AST:
eval("var x=5"); // declares x as 5, just a string literal and a function call
new Function("window.x = 5")();// or global in node
In node.js this can also be done with the vm module. In the browser using document.write or script tag injection.
What else? Of course they can obfuscate all they want:
new Function(["w","i","n","dow.x"," = ","5"].join(""))(); // Good luck finding this!
new Function('new Function(["w","i","n","dow.x"," = ","5"].join(""))()')();// Getting dizzy already?
So what can be done?
Execute the code, once, in a closed, timed environment when you update the symbol table (just the relevant parts)
See what's the generated symbol table is from the execution
Boom, you got yourself a symbol table.
This is not reliable but it's probably as close as you get.
The only other alternative I can think of, which is what most IDEs are doing is to simply ignore anything that is not:
object.property = ... //property definition
var a = ... //scoped
b = ... //global, or error in strict mode
function fn(){ //function declaration
object["property"] //property with a _fixed_ literal in bracket notation.
And also, function parameters.
I have seen no IDE that has been able to deal with anything but these. Since they're the most common by far, I think it's perfectly reasonable to count those.
By adding them onto am object that already exists....ie
window.mynewvar = 5;
function mynewfunc() {
}

How javascript || (or) operator works

In the following JavaScript statement:
var a = true;
a = a || b;
Will the a variable have an unneeded reasignment to it's own value?
Yes it will assign to a. This sort of thing probably wouldn't even be optimised in a compiled language.
It won't however waste time evaluating b however as it knows the result already. Something like this happens when a = a || b is run:
if a
a = a
else
a = b
EDIT:
To follow up what icktoofay said "it will not significantly impact performance.", it is simply setting a (boolean) variable which is one of the simplest operations that can occur. It will make little difference even if you're assigning to something more significant like a function or array as it will be assigning to a reference of the item, not creating it again.
Here is a performance comparison of doing nothing vs assigning to self (jsPerf link) thanks to #bfavaretto for setting it up.
a will be true when a or b is true. So yes, unless you insert some more code between those lines which can affect the value of a, the lower statement will always set a to true.
Yes - it won't be optimised away, because JavaScript doesn't optimise. Although the underlying parser implementation could conceivably optimise, I very much doubt it would in this case, and it would be very specific to the platform implementation.

Categories

Resources