As a developer working with hybrid mobile apps, I recently ran into a frustrating issue while testing my project on a Windows Phone using the PhoneGap Developer App. I was excited to see my app come to life, but instead of my UI, I was greeted with a JavaScript error that said:
Object doesn't support property or method "defineProperty"
At first, I was confused because the same code worked flawlessly when I opened the HTML page in the Windows Phone browser. So I decided to dig into it and in this post, I’ll walk you through the error, explain why it happens, and share the fix that worked for me, along with some practice code you can play with.
The Code That Caused the Error
Here’s the snippet that triggered the issue:
Object.defineProperty(Detail, "name", {
get: function () { return this._name; },
set: function (value) { this._name = value; },
enumerable: true,
configurable: true
});
This code uses Object.defineProperty
to create a getter/setter for the name
property on a JavaScript object. It’s perfectly valid in modern browsers and in fact, when I tested it directly in the Windows Phone 8.1 browser, it worked fine.
But when I launched the app using the PhoneGap Developer App, the exact same code threw that dreaded error.
What’s Going On
The Real Problem
The issue lies in the JavaScript engine used by the PhoneGap Developer App on Windows Phone. While the built-in browser on Windows Phone supports ECMAScript 5 features like Object.defineProperty
, the WebView engine embedded in the PhoneGap Developer App does not or at least, it doesn’t support them fully, especially for plain JavaScript objects.
So although Object.defineProperty
might work on DOM elements (like document.body
), it fails on regular objects (like my Detail
object) when run inside the PhoneGap Developer App.
Fix That Worked for Me
To solve the issue, I had two choices: either avoid using Object.defineProperty
altogether or implement a fallback method.
Avoid Object.defineProperty
I replaced the property definition with direct assignment and added simple functions to handle setting and getting values.
Detail = {
_name: "Default Name",
setName: function (value) {
this._name = value;
},
getName: function () {
return this._name;
}
};
Detail.setName("Zoya");
console.log(Detail.getName()); // Output: Zoya
This approach gave me complete compatibility and worked smoothly across all devices, including Windows Phone.
Polyfill for Older Engine
I also tried using a polyfill for environments that don’t support Object.defineProperty
. But be warned: this doesn’t provide full support especially not in legacy WebViews.
(typeof Object.defineProperty !== 'function') {
Object.defineProperty = function(obj, prop, descriptor) {
if (descriptor.get) {
obj["get" + prop] = descriptor.get;
}
if (descriptor.set) {
obj["set" + prop] = descriptor.set;
}
return obj;
};
}
This acts as a kind of fallback and helps avoid runtime crashes, but it’s not a perfect solution.
Safe Property Handle
To reinforce what I learned, I created a practice-friendly version of the code using direct methods. It’s simpler, readable, and works everywhere:
Detail = {
_name: "Initial Name",
setName: function(name) {
this._name = name;
},
getName: function() {
return this._name;
},
print: function() {
console.log("Name is: " + this.getName());
}
};
// Practice usage
Detail.print(); // Output: Name is: Initial Name
Detail.setName("Zoya");
Detail.print(); // Output: Name is: Zoya
This pattern not only avoids compatibility issues, but it also makes your code more readable and easier to debug.
Ditch the Developer App for Real Build
If you’re using Windows Phone, I recommend building your project using the PhoneGap CLI instead of testing through the Developer App. Just run:
cordova build windows
This will generate a real Windows app package that runs with the full system browser engine instead of the outdated WebView used by the Developer App.
Final Thought
Dealing with legacy JavaScript engines can be frustrating especially when your code works in one browser but crashes in another. This Object.defineProperty
issue is a perfect example of why understanding your runtime environment is just as important as writing clean code.
By falling back to simpler approaches and avoiding newer syntax where it’s unsupported, I was able to get my app working again even on older phones. I hope this helped you if you’re facing the same problem.
Feel free to modify the sample project above and explore how JavaScript objects behave across environments. And remember: compatibility first, cleverness second.