To ensure proper functionality, encasing the assignment in a function or at least on the right-hand side can help:
objects[i].callback = (function(i) { return function(e, x, y) {
cb(e, x, y, i);
})(i);
The initial anonymous function is immediately triggered, transferring the loop variable "i" into an argument (also identified as "i"; some find this approach confusing while others argue it's clearer not to change names, so the choice is yours), which is utilized by the inner anonymous function that gets returned.
An alternative solution involves utilizing a utility function instead of an inline anonymous function. The complexity arises from desiring "i" to be the final parameter of the actual callback function. The Functional JavaScript library offers a useful utility for preloading certain arguments with fixed values, generating a function that permits you to input arguments for the non-fixed parameters. An implementation could resemble this:
objects[i].callback = (function(e, x, y, i) { return cb(e, x, y, i); }).partial(_, _, _, i);
Whether this method is more favorable or less is subject to personal style and perspective.
edit after indulging in a bit more coffee - upon further review, using "partial()" may have been an unnecessary complication. It appears that positioning "i" as the last parameter for the innermost (actual) function doesn't fundamentally impact the configuration. Therefore, the previous example could also be restructured like this:
objects[i].callback = (function(i, e, x, y) { return cb(e, x, y, i); }).curry(i);
This alteration is much more straightforward. (Both approaches should suffice, or at least I believe they would. :-)