0

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

  • 从 SQLite 数据库的多个不同表中获取结果
  • 将对象返回给各种控制器函数

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

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

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

  • 我需要能够覆盖返回对象中的一些属性(即需要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方法手动更改属性描述符?
- 为什么enumerable: true默认值应该是 false ?这与 SQlite 数据库事务有关吗?
- 为什么默认值writable: false, enumerable: false, configurable: false不应用于使用 JSON 方法克隆的新对象?
答案这里- 取决于对象的创建方式 - 请参阅下面的评论

4

1 回答 1

0

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

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


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

无论出于何种原因,这都会导致对象带有
writable: true, enumerable: true, configurable: true (在 Chrome 和 Safari 中测试) (是的,鉴于规范中列出的所有 3 个描述符
的默认值,这没有意义)编辑: 这是因为对象的定义方式- 见这里 - 像所有属性描述符一样定义默认为 true, - 像任何未定义描述符一样定义默认为 falsefalse


myObject={}; myObject.a=1;
Object.defineProperty(myObject, 'a', { value: 1 });

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

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

于 2014-12-31T00:44:19.760 回答