I'm writing an AngularJS service provider (function) that:
The service queries different tables (which have different columns) so the result
object has different properties - depending on which table the data was sourced from.
Object.defineProperties
for specific object properties since i don't know the properties prior to the query 'case' being created When the object is returned to the controller functions there is some manipulation required
writable: true
) writable: false
Question:
How do i define an object to have attributes configurable: true, writable: true, enumerable: true
for all (future) properties of an object ? ie how to set the default attributes for an object since I don't (yet) know the exact property names of the object ?
Sample code:
this.checkRowExists = function(table, id) {
try {
var deferred = $q.defer();
switch (table) {
case "table1" :
var selectQuery = 'SELECT * FROM ' + table + ' WHERE id=?';
break;
case "table2" :
var selectQuery = 'SELECT * FROM ' + table + ' WHERE id=?';
break;
case "table3" :
var selectQuery = 'SELECT * FROM ' + table + ' WHERE id=?';
break;
}
this.db.transaction(function(tx) {
tx.executeSql(selectQuery, [id], function(tx, results) {
if (results.rows.length > 0){
var myRow = {}; // <- how to define all properties in "myRow" object as configurable and writable ??
var myRow = results.rows.item(0);
deferred.resolve(myRow); // <- object "myRow" is returned here to various controller functions
} else {
deferred.resolve(results.rows.length);
}
}, function(tx, error) {
console.log('checkRowExists: Error occurred while searching for profile.', error);
deferred.reject(error);
});
});
return deferred.promise;
} catch(exception) {
console.log('checkRowExists: Error occurred while trying this function.', exception);
}
};
PS the code works fine, but just returns an object with writable: false, enumerable: true, configurable: false
while i need everything to be true
EDIT:
Questions remaining even after partial solution below:
- why can't a property descriptor be changed manually using the Object.defineProperty
method ?
- why is enumerable: true
when the default should be false ? is this related to SQlite db transactions?
- why are the defaults of writable: false, enumerable: false, configurable: false
not being applied to the new object being cloned using the JSON method?
Answer is here - depends on how the object is created - see comment below
half the problem seems to be that the object myRow
inherits the property descriptors / attributes of the object that it is copied from ie:
var myRow = results.rows.item(0)
the other half of the problem is that it doesn't seem possible to change the property descriptors:
ie using Object.defineProperty(myRow, "my_property", {configurable: true});
-> gives TypeError: Cannot redefine property: my_property
PARTIAL SOLUTION
according to the 3rd answer in this discussion the most elegant way to clone an object is to use:
var newObject = JSON.parse(JSON.stringify(oldObject));
which seems to create an entirely new object, that doesn't inherit property descriptors from the 'copied' object
for whatever reason this results in an object with
writable: true, enumerable: true, configurable: true
(tested in Chrome & Safari)
(and yes that doesn't make sense given the defaults of false
for all 3 descriptors listed in the spec )
EDIT:
this is because of the way the object is defined - see here
- defined like myObject={}; myObject.a=1;
myObject={}; myObject.a=1;
all property descriptors default to true,
- defined like Object.defineProperty(myObject, 'a', { value: 1 });
any undefined descriptors default to false
so the output of the following snippet from the code above looks like:
tx.executeSql(selectQuery, [id], function(tx, results) {
if (results.rows.length > 0){
// see what the original object descriptors are set at:
console.log( Object.getOwnPropertyDescriptor(results.rows.item(0), "my_property") );
// -> outputs "configurable: false, enumerable: true, writable: false"
var myRow = results.rows.item(0);
// see what the new copied object descriptors are set at:
console.log( Object.getOwnPropertyDescriptor(myRow, "my_property") );
// -> outputs "configurable: false, enumerable: true, writable: false"
var myRow2 = JSON.parse(JSON.stringify(results.rows.item(0)));
// see what the new JSON cloned object descriptors are set at:
console.log( Object.getOwnPropertyDescriptor(myRow, "my_property") );
// -> outputs "configurable: true, enumerable: true, writable: true"
deferred.resolve(myRow2);
} else {
deferred.resolve(results.rows.length);
}
}, function(tx, error) {
console.log('checkRowExists: Error occurred while searching for profile.', error);
deferred.reject(error);
});
still have a couple of questions about this partial solution:
- what is the speed of using JSON.parse(JSON.stringify(object));
to copy / clone an object ?
- are there other disadvantages of using JSON.parse(JSON.stringify(object));
to clone ?
(some are listed here - mostly doesn't work with date formats or function within object properties)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.