Most of the time you'll want to use Object.defineProperty(). But in the unusual case where you need to test the success of the operation, you'll want to use Reflect.defineProperty().
That's because it doesn't throw an error if your property definition fails due to an existing non-configurable property or non-extensible object. That means you don't need a try/catch block if you want to know if property definition was successful or not. You can just check the return value which will be true or false.
Furthermore with Object.defineProperty() using try/catch to test for success is problematic because there are other reasons why your code might throw. For example it would be a programming error if the target is not an object, or the descriptor attributes include both get or set and value or writable. In such cases it's better not to catch the error making try/catch undesirable. Try/catch is also notoriously slow.
So with Reflect.defineProperty() try/catch is not needed to discover the success of the operation, and you still have the advantage that it throws if there is a problem with the target value or the descriptor. The only caveat is that Reflect.defineProperty() is not supported in ES5 browsers. But the good news is that it can easily be polyfilled:
self.Reflect = self.Reflect || {};
Reflect.defineProperty = Reflect.defineProperty || function defineProperty(obj, prop, descriptor) {
if (Object(obj)!==obj) {
throw TypeError("Reflect.defineProperty called on non-object")
}
prop in obj;// throw if prop cannot convert to string/symbol
if ("get" in descriptor || "set" in descriptor) {
if (typeof descriptor.get!="function" && typeof descriptor.get!="undefined") {
throw TypeError("property descriptor's get field is neither undefined nor a function")
}
if (typeof descriptor.set!="function" && typeof descriptor.set!="undefined") {
throw TypeError("property descriptor's set field is neither undefined nor a function")
}
if ("value" in descriptor || "writable" in descriptor) {
throw TypeError("property descriptor's attributes cannot contain both get or set and value or writable")
}
}
try {
var success = Object.defineProperty(obj, prop, descriptor);
}
catch(e) {
}
return !!success
}