如何同时为对象的所有属性定义属性(或设置默认值)

时间:2014-12-30 21:34:07

标签: javascript angularjs object properties defineproperty

我正在编写一个AngularJS服务提供程序(函数):

  • 从SQLite数据库的许多不同表中获取结果
  • 将对象返回到各种控制器功能

服务查询不同的表(具有不同的列),因此result对象具有不同的属性 - 具体取决于数据源自哪个表。

  • 因此我无法将Object.defineProperties用于特定的对象属性,因为我不知道在创建查询“case”之前的属性
  • 我想我可以在'switch'中定义对象变量属性,但这看起来很乱......

当对象返回到控制器功能时,需要进行一些操作

  • 我需要能够覆盖返回对象中的一些属性(即需要writable: true
  • 准确地说,JSON.parse()然后覆盖各种属性,因为存储在SQLite DB中的数组在INSERT之前用JSON.stringify()转换,然后在DB中存储为字符串
  • 我遇到了麻烦,因为对象的默认值是writable: false

问题:
如何为对象的所有(未来)属性定义一个具有属性configurable: true, writable: true, enumerable: true的对象?即如何设置对象的默认属性,因为我不(还)知道对象的确切属性名称?

示例代码:

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代码工作正常,但只返回writable: false, enumerable: true, configurable: false的对象,而我需要一切true

编辑:
即使在以下部分解决方案后仍存在问题:
- 为什么不能使用Object.defineProperty方法手动更改属性描述符?
- 当默认值为false时,为什么enumerable: true?这与SQlite数据库事务有关吗? - 为什么writable: false, enumerable: false, configurable: false的默认值没有应用于使用JSON方法克隆的新对象? 答案here - 取决于对象的创建方式 - 请参阅下面的评论

1 个答案:

答案 0 :(得分:0)

问题的一半似乎是对象myRow继承了从中复制的对象的属性描述符/属性,即:
var myRow = results.rows.item(0)

问题的另一半是,似乎无法改变属性描述符:
即使用Object.defineProperty(myRow, "my_property", {configurable: true});
- &GT;给出TypeError: Cannot redefine property: my_property

部分解决方案
根据{{​​3}}中的第3个答案,克隆对象最优雅的方法是使用:
var newObject = JSON.parse(JSON.stringify(oldObject));
这似乎创造了一个全新的对象,它不会从“复制”中继承属性描述符。对象

无论出于何种原因,都会产生一个具有
的物体 writable: true, enumerable: true, configurable: true(在Chrome和Safari中测试过)
(对于this discussion中列出的所有3个描述符的false的默认值,这是没有意义的) 修改
这是因为对象的定义方式 - 请参阅spec
- 定义为myObject={}; myObject.a=1;所有属性描述符默认为true,
- 定义为Object.defineProperty(myObject, 'a', { value: 1 });任何未定义的描述符默认为false

所以上面代码中以下代码段的输出如下所示:

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);
});

对这个部分解决方案仍然有几个问题:
- 使用JSON.parse(JSON.stringify(object));复制/克隆对象的速度是多少? - 使用JSON.parse(JSON.stringify(object));进行克隆有其他缺点吗?
(有些列出here - 大部分都不适用于对象属性中的日期格式或函数)