Qtified JavaScript

When writing JavaScript code, it doesn't take long until I'm missing some function which is available in Qt's C++ API. One very simple example is QList::contains. Checking whether an array contains a certain element works like this in JavaScript:

var names = ["Egon", "Peter", "Raymond", "Waldo"];
if (names.indexOf("Waldo") !== -1)
print("We've found him!");

It would be nice if we could express the condition using a contains method but Array doesn't provide one.
Luckily, JavaScript enables us to add methods to inbuilt types by modifiying the corresponding prototype object.

Array.prototype.contains = function(e) {
return this.indexOf(e) !== -1;
}
if (names.contains("Waldo"))
print("We've found him!");

Yay! Now we can use the contains method for all arrays!
But wait - there's a surprise lurking right around the corner once you're trying to iterate over the keys of the array.

for (var i in names)
print(i);

This will print:

0
1
2
3
contains

I know, iterating over arrays should be done with an index variable...but still...this additional key is unexpected and asking for trouble.

The solution for this problem is to mark the property contains as non-enumerable. We can use the Object.defineProperty function for that which is available since JavaScript 1.8.5.

Object.defineProperty(Array.prototype, "contains", {
value: function(e) { return this.indexOf(e) !== -1; },
enumerable: false    // This is the default and can be omitted.
})

We're passing to Object.defineProperty the object we want to enhance, the name of the property we want to add and a descriptor object that contains the attributes of our new property.
The value of  contains will be the function that we formerly passed directly to the prototype. Setting the enumerable property to false in the descriptor object will hide contains when using a for (... in ...) loop.

This way we can create a nice Qtish API for the inbuilt JavaScript types Array and String. This can be put into a .js file and used it in QML/JS or in qbs project files.

What do you think? Would such an API be helpful for your QML code? Which QList or QString method are you missing most?


Blog Topics:

Comments