【问题标题】:JavaScript: Keep methods after serializationJavaScript:序列化后保留方法
【发布时间】:2014-11-24 12:57:52
【问题描述】:

我被一个更大的 JavaScript 应用程序(使用 jQuery Mobile)困住了,其中大部分程序逻辑已经实现。现在我想向它添加序列化(使用一个名为 JStorage 的插件)。在这个代码示例中,我将一个对象字符串化为 JSON,然后再次将其转换为一个对象(全部没有 JStorage),但是我添加到原始对象的方法会丢失,如下代码所示:

function TestObject() {
    this.lang = "English";
}

// This is the method I want to keep
TestObject.prototype.showLang = function() {
    console.log(this.lang)
};

var test1 = new TestObject();
var test2 = $.parseJSON(JSON.stringify(test1)); // After save and reload
test1.showLang(); // This works
test2.showLang(); // This causes an error

问题还有一个限制:在代码中,我经常使用点运算符来调用函数,如test1.showLang()。我知道我可以添加一个像这样的“全局”函数,它既适用于原版,也适用于副本:

function showLang(obj) {
    console.log(obj.lang);
}

但是我必须将每个现有的函数调用从 test1.showLang() 更改为 showLang(test1) - 在我的真实项目中- 我将不得不在整个代码中执行数百次。那么有没有更简单的解决方案如何在序列化后在对象上使用现有函数?

【问题讨论】:

    标签: javascript json serialization methods jstorage


    【解决方案1】:

    据我所知,JSON 不具备序列化方法然后反序列化它们的能力。它主要用于 DTO(数据传输对象),而不是对象代理。

    附带说明的是,如果 JSON 确实支持它,它可能是一个重大的安全漏洞。

    【讨论】:

    • 我知道,我不想序列化方法。 JSON 仅对变量进行序列化,然后 $.parseJSON() 将它们再次放入一个新对象中。但是我怎样才能将 TestObject.prototype.showLang() 用于对象 test2?
    【解决方案2】:

    您可以更改您的 TestObject 构造函数,以便它可以接受包含其所有属性的可选初始值的对象:

    function TestObject(properties) {
        this.lang = (properties && !(properties.lang === undefined)) ? properties.lang : "English";
    }
    

    然后使用你的反序列化对象使用构造函数创建一个新对象,而不是直接使用反序列化对象:

    var test2 = new TestObject( $.parseJSON(JSON.stringify(test1)) );
    

    这似乎有效:http://jsfiddle.net/wubfckez/

    【讨论】:

    • 我在我的项目中将您的解决方案付诸实践,并且效果很好,但是我不得不对代码进行大量更改,因为我需要重写每个构造函数并且我的对象可以嵌套(包括其他对象),这可能很棘手。非常感谢,但如果有人有其他需要较少更改的解决方案,我很乐意在未来听到它。
    • @user3742403:很高兴听到它有效。在某些浏览器中,您可以在对象创建后更改其原型(我相信使用 __proto__ 属性),但据我所知,这不太可能成为未来的标准 JavaScript 功能。
    • 那我继续使用prototype。还有一件事:您发布的代码似乎适用于字符串,但整数(如果为 0)和布尔值(如果为假)可能会成为问题,因为“||”如果整数/布尔值未定义,则运算符的行为将是。在这种情况下,我更喜欢: this.myInt = (properties && typeof properties.myInt !== 'undefined') ?属性.myInt:55;如果 properties.myInt 未定义,将使用 55,如果 properties.myInt 为 0 或其他数字,将使用该数字。
    • @user3742403: 哦,当然,我没想到这一点,很好。我会相应地修改我的答案。
    • @user3742403:可能值得编写一个函数来循环遍历对象的所有属性,并将它们分配为另一个对象的同名属性(即对象合并函数)。很多框架都有这样的功能;例如在下划线中,它是“扩展”功能。
    猜你喜欢
    • 2018-12-11
    • 2021-11-28
    • 1970-01-01
    • 1970-01-01
    • 2017-08-17
    • 2010-10-13
    • 2016-09-01
    • 2016-07-16
    • 1970-01-01
    相关资源
    最近更新 更多