Why this huge performance difference for an encapsulated Javascript function? - javascript

So I have this simple code:
function Run () {
var n = 2*1e7;
var inside = 0;
while (n--) {
if (Math.pow(Math.random(), 2) +
Math.pow(Math.random(), 2) < 1)
inside++;
}
return inside;
}
var start = Date.now();
Run();
console.log(Date.now() - start);
And it will output some time around 335ms. That's pretty good. But, if I encapsulate the Run function like this:
var d = Date.now();
(function Run () {
var n = 2*1e7;
var inside = 0;
while (n--) {
if (Math.pow(Math.random(), 2) +
Math.pow(Math.random(), 2) < 1)
inside++;
}
return inside;
})();
console.log(Date.now() - d);
It will output 18319ms, which is much worse than the case before. Why is this ?
Also, if it matters, I'm running it on Chrome 26.0.1410.63, in the console. On node.js both snippets perform well on the console.

There is no difference with function decleration and function expressions WRT to optimization, that would be ridiculous.
Console code in Google Chrome is wrapped in with statement like this:
with ((console && console._commandLineAPI) || {}) {
//Your code is concatenated here
}
Because function declarations are hoisted, the former code will be effectively this:
function Run () {
var n = 2*1e7;
var inside = 0;
while (n--) {
if (Math.pow(Math.random(), 2) +
Math.pow(Math.random(), 2) < 1)
inside++;
}
return inside;
}
with ((console && console._commandLineAPI) || {}) {
var start = Date.now();
Run();
console.log(Date.now() - start);
}
So the declaration is running outside with statement. In fact it is not valid syntax to have function declaration in a block, function declaration can only be a top level statement.
So anyway because of historical reasons V8 is nice and hoists it out instead of throwing syntax error:
var i = 3;
with({i:4}) {
function test() {
console.log(i);
}
}
test();//logs 3 so it is obviously **not** under `with` influence
So because the declaration is not under with statement, it will run much faster. With statement is not optimizable* under V8 and also breaks lexical scoping.
*Not optimizable means the optimizing compiler will not look at the code instead only the generic compiler will generate code for the function. It is comparable to firefox's interpreter vs JIT mode. If you wish to know more about what language features disable optimization in V8, read optimization killers

Related

JSHint referencing an outer scope

Hi I have problem with JSHint, cause always getting
Functions declared within loops referencing an outer scoped variable may lead to confusing semantics. ($, totals).
My function call is
var a;
a.each(function (c) {
if (c.length == 0) return;
for (var index in c) {
var test = {};
a.each(function (e) {
var idx = $(e).data('index');
if (idx in test) {
test[idx] += $(e).data('key');
} else {
test[idx] = $(e).data('key');
}
});
}
});
I know that problem because I accessing test variable in the callback, but is there a solution for this, something to rewrite code or to tell JSHint to not throw warning
may should rather be rarely or theoretically. In most cases (like this one) this hint isn't useful at all and can safely be ignored (or disabled).
The rare case is something like this:
for(var i = 0; i < 10; i++) { // loop
setTimeout(function() { // callback
console.log(i); // outer reference
}, 100);
}
and JSHint tries to warn you in this case, but the scenario that triggers the warning for this reasonable case, occurs very often, and then the warning isn't useful at all (as with jQuery's global).

Reflection/Introspection of JavaScript Modules

Assume I have:
// test.js
function myFunc(a,b,c) {
return "Test";
}
module.exports.myFunc = myFunc;
How can I dynamically find out that test.js has a function myFunc which takes 3 parameters, so:
x = require('test.js')
if ( x has function defined myFunc ) {
if ( function myFunc in x has 3 arguments) {
"OK"
} else { "Expect 3 params"}
} else {
"test.js does not expose myFunc" }
Is this possible using reflection/introspection?
Thanks
This isn't specific to modules. Function arity can be determined with length property in JavaScript, myFunc.length === 3.
Relying on length in production is contradictory practice that often designates code smell. In tests, expected length behaviour may be undesirable.
Not too good:
function myFunc(...args) {
const [a,b,c] = args;
}
myFunc.length === 0;
Not good at all:
function myFunc(a, b = 1, c = 2) {}
myFunc.length === 1;
If myFunc.length is expected to be used in unit tests, it's recommended to skip this assertion and focus on function behaviour instead.

Why need apply in memoization function?

I've been toyin with concept of memoization and there are obviously different implementations of it. I put this together and it seems to work fine:
Function.prototype.memoized = function(a) {
debugger
if (typeof cache === "undefined") cache = [];
if (cache[a]) {
return cache[a];
} else {
cache[a] = this(a);
return cache[a];
}
}
Function.prototype.memoize=function() {
t=this;
return function() {
// Resig seems to use this:
return t.memoized.apply(t,arguments);
// why not simple this:
//return t.memoized(arguments[0]);
}
}
myTest = (function fibonacci(n) {
return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
}).memoize();
console.log(myTest(2));
My question is however why in some implementations I see
return t.memoized.apply(t,arguments); rather than simple return t.memoized(arguments[0]); inside of proptotype.memoize? I cannot see any advantage apart from passing multiple arguments which are not used anyway. I there any advantage to apply?
EDIT:
Updated the code and I believe this takes care of major problems so cache as global on window (what was I thinking??) and recursive fibonacci not memoizing calls to itself. Are there any other major issue with my implementation?
Function.prototype.memoized = function(a) {
if (typeof this.cache === "undefined") this.cache = [];
if (this.cache[a]) {
return this.cache[a];
} else {
this.cache[a] = this(a);
return this.cache[a];
}
}
Function.prototype.memoize=function() {
t=this;
return function() {
//return t.memoized.apply(t,arguments);
return t.memoized(arguments[0]);
}
}
myTest = (function fibonacci(n) {
//return a * 3;
return n < 2 ? n : fibonacci.memoized(n - 1) + fibonacci.memoized(n - 2);
}).memoize();
console.log(myTest(2));
BTW this is learning experience for me and doing it purely for fun, it's not assignment or anything like that uni related.
In general, JavaScript functions are variadic, which means that you would need to pay attention to all of them actually. Some memoize implementations do this by using JSON.stringify(arguments) for the cache key.
In this case, it does not make any sense, since the memoized method does only use a single argument as well.
However, there are more serious bugs in your code than this little inaccuracy. cache is a global variable, while it should be bound to the specific memoized function. Also, your fib implementation is not memoized in the recursive call, where it actually is the most important.
The edited version looks good (except for the global t variable). In personal, I would have shortened/simplified the code a little bit however:
Function.prototype.memoize=function() {
var t = this;
this.cache = [];
return function(a) {
var cache = t.cache;
if (typeof cache[a] == "undefined")
cache[a] = t(a);
return cache[a];
};
}
var fibonacci = (function (n) {
return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
}).memoize();
console.log(fibonacci(2));

Calling a javascript function recursively

I can create a recursive function in a variable like so:
/* Count down to 0 recursively.
*/
var functionHolder = function (counter) {
output(counter);
if (counter > 0) {
functionHolder(counter-1);
}
}
With this, functionHolder(3); would output 3 2 1 0. Let's say I did the following:
var copyFunction = functionHolder;
copyFunction(3); would output 3 2 1 0 as above. If I then changed functionHolder as follows:
functionHolder = function(whatever) {
output("Stop counting!");
Then functionHolder(3); would give Stop counting!, as expected.
copyFunction(3); now gives 3 Stop counting! as it refers to functionHolder, not the function (which it itself points to). This could be desirable in some circumstances, but is there a way to write the function so that it calls itself rather than the variable that holds it?
That is, is it possible to change only the line functionHolder(counter-1); so that going through all these steps still gives 3 2 1 0 when we call copyFunction(3);? I tried this(counter-1); but that gives me the error this is not a function.
Using Named Function Expressions:
You can give a function expression a name that is actually private and is only visible from inside of the function ifself:
var factorial = function myself (n) {
if (n <= 1) {
return 1;
}
return n * myself(n-1);
}
typeof myself === 'undefined'
Here myself is visible only inside of the function itself.
You can use this private name to call the function recursively.
See 13. Function Definition of the ECMAScript 5 spec:
The Identifier in a FunctionExpression can be referenced from inside the FunctionExpression's FunctionBody to allow the function to call itself recursively. However, unlike in a FunctionDeclaration, the Identifier in a FunctionExpression cannot be referenced from and does not affect the scope enclosing the FunctionExpression.
Please note that Internet Explorer up to version 8 doesn't behave correctly as the name is actually visible in the enclosing variable environment, and it references a duplicate of the actual function (see patrick dw's comment below).
Using arguments.callee:
Alternatively you could use arguments.callee to refer to the current function:
var factorial = function (n) {
if (n <= 1) {
return 1;
}
return n * arguments.callee(n-1);
}
The 5th edition of ECMAScript forbids use of arguments.callee() in strict mode, however:
(From MDN): In normal code arguments.callee refers to the enclosing function. This use case is weak: simply name the enclosing function! Moreover, arguments.callee substantially hinders optimizations like inlining functions, because it must be made possible to provide a reference to the un-inlined function if arguments.callee is accessed. arguments.callee for strict mode functions is a non-deletable property which throws when set or retrieved.
You can access the function itself using arguments.callee [MDN]:
if (counter>0) {
arguments.callee(counter-1);
}
This will break in strict mode, however.
You can use the Y-combinator: (Wikipedia)
// ES5 syntax
var Y = function Y(a) {
return (function (a) {
return a(a);
})(function (b) {
return a(function (a) {
return b(b)(a);
});
});
};
// ES6 syntax
const Y = a=>(a=>a(a))(b=>a(a=>b(b)(a)));
// If the function accepts more than one parameter:
const Y = a=>(a=>a(a))(b=>a((...a)=>b(b)(...a)));
And you can use it as this:
// ES5
var fn = Y(function(fn) {
return function(counter) {
console.log(counter);
if (counter > 0) {
fn(counter - 1);
}
}
});
// ES6
const fn = Y(fn => counter => {
console.log(counter);
if (counter > 0) {
fn(counter - 1);
}
});
I know this is an old question, but I thought I'd present one more solution that could be used if you'd like to avoid using named function expressions. (Not saying you should or should not avoid them, just presenting another solution)
var fn = (function() {
var innerFn = function(counter) {
console.log(counter);
if(counter > 0) {
innerFn(counter-1);
}
};
return innerFn;
})();
console.log("running fn");
fn(3);
var copyFn = fn;
console.log("running copyFn");
copyFn(3);
fn = function() { console.log("done"); };
console.log("fn after reassignment");
fn(3);
console.log("copyFn after reassignment of fn");
copyFn(3);
Here's one very simple example:
var counter = 0;
function getSlug(tokens) {
var slug = '';
if (!!tokens.length) {
slug = tokens.shift();
slug = slug.toLowerCase();
slug += getSlug(tokens);
counter += 1;
console.log('THE SLUG ELEMENT IS: %s, counter is: %s', slug, counter);
}
return slug;
}
var mySlug = getSlug(['This', 'Is', 'My', 'Slug']);
console.log('THE SLUG IS: %s', mySlug);
Notice that the counter counts "backwards" in regards to what slug's value is. This is because of the position at which we are logging these values, as the function recurs before logging -- so, we essentially keep nesting deeper and deeper into the call-stack before logging takes place.
Once the recursion meets the final call-stack item, it trampolines "out" of the function calls, whereas, the first increment of counter occurs inside of the last nested call.
I know this is not a "fix" on the Questioner's code, but given the title I thought I'd generically exemplify Recursion for a better understanding of recursion, outright.
Using filter and map, recursion example removing null properties from an object
const obj = {
name: {
first: "Jeson",
middle: null,
last: "Holder"
},
age: 45
}
function removeNullOrEmpty(obj){
return Object.fromEntries(
Object.entries(obj)
.filter(([_, v])=> v!== null && v.length !== 0)
.map(([k, v])=>[k, v === Object(v)?removeNullOrEmpty(v):v])
)
}
console.log(removeNullOrEmpty(obj))

Weird Event Listening in ActionScript3

I have a weird quirk in ActionScript. I need to pass the index to a callback function.
Here is my code
for (var i:Number = 0; ((i < arrayQueue.length) && uploading); i++)
{
var lid:ListItemData=ListItemData(arrayQueue[i]);
var localI:Number= new Number(i); // to copy?
var errorCallback:Function = function():void { OnUploadError(localI); };
var progressCallback:Function = function(e:ProgressEvent):void { lid.progress = e; OnUploadProgress(localI); };
var completeCallback:Function = function():void { Alert.show('callback'+localI.toString()); OnUploadComplete(localI); }; // localI == arrayQueue.length - 1 (when called)
Alert.show(localI.toString()); // shows current i as expected
lid.fileRef.addEventListener(Event.COMPLETE, completeCallback);
lid.fileRef.addEventListener(ProgressEvent.PROGRESS, progressCallback);
lid.fileRef.addEventListener(HTTPStatusEvent.HTTP_STATUS, errorCallback);
lid.fileRef.addEventListener(IOErrorEvent.IO_ERROR, errorCallback);
lid.fileRef.addEventListener(SecurityErrorEvent.SECURITY_ERROR, errorCallback);
lid.fileRef.upload(url, 'File');
}
Any idea on how to pass in the index to my callbacks? .upload does not block.
Passing additional parameters for your callbacks is possible via some kind of delegate function or closure. However it is often considered a bad practice. You may use event target property instead to determine your index based on FileReference.
Edit: here is a sample of using closures:
function getTimerClosure(ind : int) : Function {
return function(event : TimerEvent) {
trace(ind);
};
}
for (var i = 0; i < 10; i++) {
var tm : Timer = new Timer(100*i+1, 1);
tm.addEventListener(TimerEvent.TIMER, getTimerClosure(i));
tm.start();
}
This will continuously trace numbers from 0 to 9.
Edit2: here is a sample of creating a delegate based on a function closure:
function timerHandler(event : Event, ...rest) : void {
trace(event, rest);
}
function Delegate(scope : Object, func : Function, ...rest) : Function {
return function(...args) : void {
func.apply(scope, args.concat(rest));
}
}
var tm : Timer = new Timer(1000, 1);
tm.addEventListener(TimerEvent.TIMER, Delegate(this, this.timerHandler, 1, 2, 3));
tm.start();
However this is a bad approach since unsubscribing for such a listener is a hell pain. This in turn will probably cause some memory leakages, which will decrease overall performance of your application. So, use with caution!
Bottom line: if you know how to work with closures, use them - it is a wonderful thing! If you don't care about your application performance in a long perspective, use closures - it's simple!
But if you are unsure about closures, use a more conventional approach. E.g. in your case you could create a Dictionary that matches your FileReference objects to appropriate indices. Something like that:
var frToInd : Dictionary = new Dictionary(false);
// false here wouldn't prevent garbage collection of FileReference objects
for (var i : int = 0; i < 10; i++) {
// blah-blah stuff with `lib` objects
frToInd[lib.fileRef] = i;
// another weird stuff and subscription
}
function eventListener(event : Event) : void {
// in the event listener just look up target in the dictionary
if (frToInd[event.target]) {
var ind : int = frToInd[event.target];
} else {
// Shouldn't happen since all FileReferences should be in
// the Dictionary. But if this happens - it's an error.
}
}
-- Happy coding!
I have a weird quirk in ActionScript
It's not a quirk, it's variable scope. You should read this article: http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7f9d.html#WS5b3ccc516d4fbf351e63e3d118a9b90204-7f8c
And you really shouldn't use anonymous, it just makes everything more confusing. You're actually making multiple copies of the same object.
If the arrayQueue is in scope, you can use this code to get the index:
GetArrayIndex(e.currentTarget);
function GetArrayIndex(object:Object):Number
{
for(var i:Number = 0; 0 < arrayQueue.length; i++)
{
if(object === arrayQueue[i])
return i;
}
}
You should consider using an uint for the index.

Categories

Resources