简体   繁体   中英

how to define attributes for all properties of an object simultaneously (or set default)

I'm writing an AngularJS service provider (function) that:

  • takes results from a number of different tables of an SQLite database
  • returns the object to various controller functions

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.

  • it's therefore not possible to use Object.defineProperties for specific object properties since i don't know the properties prior to the query 'case' being created
  • i suppose I could define the object variable properties within the 'switch' but that seems messy...

When the object is returned to the controller functions there is some manipulation required

  • i need to be able to overwrite some properties in the returned object (ie need writable: true )
  • to be precise, JSON.parse() then overwrite of various properties since arrays stored in the SQLite DB are converted with JSON.stringify() prior to INSERT then stored as strings in the DB
  • i'm running into trouble since the default for the object is 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM