Sometimes language and platform abstractions bite you. They can seem pretty straightforward and “just like the real thing”, but sometimes they have odd behaviors that don’t quite work the way you expect.
Dynamic method invocation with .call() and .apply()
.apply() functions are something you will use a lot if your code involves a lot of dynamic arguments, such as building an array of arguments that then need to be mapped to actual ordered function arguments in a function or method call.
var args = [sql].concat(params); var db = Ti.Database.open('dbname'); var rs = db.execute.apply(db, args);
But if you run that, and you will be presented with the head-scratching error:
invalid method 'execute:'
Although the error is pretty confusing – you know there is a method named execute on the
db object – there actually is a good explanation for this behavior.
Titanium Proxy Objects
db – is actually a proxy object created and returned by Titanium with the
Ti.Database.open call. Titanium also returns proxy objects for pretty much every other component that has a native counterpart they are bridging over to behind the scenes. This black magic is fundamental to how Titanium works internally.
Although the main Titanium proxy object explanation suggests creating a wrapper object for the method call, that’s actually not necessary at all, and creates a lot of extra work, as well as many additional lines of code.
apply method directly from the
var args = [sql].concat(params); var db = Ti.Database.open('dbname'); var rs = Function.prototype.apply.call(db.execute, db, args);
This is a nice one-liner that achieves the same end result, is much easier to undertand, and does not require a wrapper object or another layer of indirection to achieve.