John Resig Talk: Performance Improvements in Browsers
ejohn.org
ejohn.org
As a corollary to that, doing
eval("function(){"+code+"}")
is much slower (~5x) than new Function(code)
at least in Firefox using 280slides.com as my test subject (which is part of the reason we do use "new Function").To your second point: Of course eval("function(){"+code+"}" is going to be a lot slower than new Function(code) - you're constructing a closure to any external variables that are used (not to mention that using eval will have to parse the full expression and return the result - rather than with new Function which has a singular purpose).
It's also interesting how little what we used to call "layout" is a performance target any more.
(I've since re-written Dromaeo - and the current version that's live is taking in to account all the problems that I outlined in this post.)
I think layout would be more of a performance target if there was a reliable way to test it across platforms - or even on a single platform (especially so from JavaScript). That's definitely something that I'd like to shoot for, though - it would be hugely helpful to developers.
I guess my thinking was -- I hear a lot of anecdotal discussion about the FireFox codebase and how it needs to be re-engineered, etc, etc (ie. WebKit is tidier and so forth).
If the performance war is elsewhere, does that remain a factor? i.e. Assuming the above is actually true, does the codebase have legs as the performance war is elsewhere?
The gist of it is: I do "document.attachEvent("onmousemove", fn)" where fn resizes a div based on where the cursor is. I then test it out, and it's slow as hell, especially when the div gets pretty big. In fact, the event only seems to fire when I move the mouse slowly.
Now here's the catch. I bind the event again so that the function is bound twice to onmousemove, and performance is vastly improved!
How could it be that binding a function twice to an event speeds it up? Three times has no further effect... beyond that I haven't tested.
EDIT: Go to my profile to see the bug in action. While resizing a div (which contains 2 iframes), it's much much smoother with the "mousemove" event attached twice.
I've found that jQuery UI plugins are bloated and slow, to be honest. There focus is on providing a dead simple interface to the developer, who might not even know how to code. I believe this leads to bloating the code and degrading performance, since the code now has to check for and include tons of these little edge cases, which can even compound themselves when they're used at the same time. In the "draggable" demos, anything being dragged is quite laggy and choppy, at least in FF, when it definitely shouldn't be.
jQuery already makes it easy enough to build whatever functionality I want, including drag and drop... and since it's not generalized (as in the case of jUI) it's fast. For drag and drop, 50 lines was all it took to pretty much copy the entire functionality of jQuery draggables... assuming the developer can code a tiny bit of functionality himself. Rather than cram all sorts of microfeatures, like "vertical-only" and "hortizontal-only", I abstract the problem out so that it puts more control in the developer's hands, but still is dead simple.
In my case, the developer defines the "init" function (triggered after it's dragged for a given length or time), the "move" function (which is passed deltaX and deltaY) and the "end" function, all of which are passed events as well. If he can't use this information to make something resize (which is just adding deltaX to originalWidth), for example, then that's too bad, he will have to use 42kb of jUI code to do it.
Another example of bloat and poor performance... if you wanted to create a Dialog, it requires Draggable, and Sortable, and comes to a total of 84kb (uncompressed). It's so laggy then when you're moving it around the shadow appears to be chasing the dialog... and resizing it lags half upwards of half a second. With jQuery, I've made draggable, resizable, shadowed dialogs in like 200 lines.
Aside, though: your e-mail isn't in your profile, and I'd like to chat - could you e-mail me at anfedorov@gmail.com, please?
Anyway, I've updated my profile... let's chat
I love Javascript so much. The fact that it has "function.call(object, other, params)" pretty much sums it up... a function can work with any object, and vice versa.
Can you explain what this does? It sounds interesting, but I don't know Javascript.
foo.barMethod("Hello", "World")
is identical to: someFunction.call(foo, "Hello", "World");
(assuming that foo.barMethod === someFunction)This is a little weirder than it seems, because of a variable called `this'. You see, `this' is set inside of a function whenever you call it, based on how you've called it. It can be set a couple of ways:
foo(arg1, arg2, ...); // sets `this' to the global object (in a browser, that's `window')
foo.call(o, arg1, arg2, ...); // sets `this' to `o'
foo.apply(o, [arg1, arg2, ...]); // sets `this' to `o' (same as `call')
None of these are the way you usually set `this' on function invocation, however. Usually, `this' is set automatically when you invoke a function which happens to be a property of an object. So, for example: bar = { foo: function (x,y) { var thatThing = this; ... } };
bar.foo(1,2) - sets `this' (and `thatThing') to 'bar'.
However (!!!), if you say: foo2 = bar.foo;
foo2();
The `this' inside of your function, as well as `thatThing', will both be set to `window'.details here: https://developer.mozilla.org/en/Core_JavaScript_1.5_Referen...
'this' is always 'window', unless the function is invoked as a method, i.e., as a property of an object:
window.bar = 'bar'
var obj = {
foo: function () { return this.bar },
bar: 'foo'
};
obj.foo() === 'foo'; // invoked as a method
foo = obj.foo;
foo() === 'bar'; // invoked as a function
// this reveals some oddness imho:
(obj.foo)() === 'foo'; // invoked as a method
(foo = obj.foo)() === 'bar'; // invoked as a function
Note that 'this' defaults to 'window' not because 'foo()' is equivalent to 'window.foo()'; 'foo' could be a local variable referring to a function and 'this' would refer to 'window' all the same. There's no rationale for this that I know of, it's just the way it works (in ES3 at least: ES4 does what you expected).When you use the Function::call and Function::apply methods, you get to specify what 'this' should refer to:
obj.foo.call(window) === 'bar';
foo.apply(obj, []) === 'foo';
'call' and 'apply' are the same, except that apply takes an array of function arguments, whereas call takes arguments directly.Note that the terms 'method' and 'function' are my own here, I'm not sure what to call the two forms of invocation.
More generally, 'this' is usually 'the global object'... would be more correct. And in a browser context, the global object is 'window'.
var foo;
foo.name = "Hi! I'm foo."
var bar;
bar.name = "I'm bar."
var alertMe = function(){ alert(this.name); }
alertMe.call(foo); //calls 'alertMe' setting 'this' to be foo
alertMe.call(bar); //same, except setting 'this' to be bar
Pretty cool, right? Methods can inherit objects! You could always have done: foo.alertMe = alertMe;
bar.alertMe = alertMe;
foo.alertMe();
bar.alertMe();