【问题标题】:Does LocalStorage support Custom (i.e. non-primitive type) Object Storage and Retrieval in any way?LocalStorage 是否以任何方式支持自定义(即非原始类型)对象存储和检索?
【发布时间】:2014-11-01 05:10:29
【问题描述】:

所以我想将 JavaScript 文件 hello.js 中的对象“Hello”传递给另一个 JavaScript 文件 chat.js。

Hello 包含 Strophe.Connections 等成员。

我读到我可以使用 LocalStorage,即 LocalStorage.SetItem("Hello", Hello),然后使用 LocalStorage.getItem("Hello") 检索对象。

这对我不起作用,所以我搜索了一下,发现 JSON stringify,例如Storing Objects in HTML5 localStorageHow to send javascript object from one page to another page? 的某人建议使用 stringify。

所以我也试了一下,下面是Hello.js的相关代码:

var Hello = {
connection: null,
start_time: null,
log: function (msg) {
    $('#log').append("<p>" + msg + "</p>");
},

send_ping: function (to) {
    var ping = $iq({
        to: to,
        type: "get",
        id: "ping1"}).c("ping", {xmlns: "urn:xmpp:ping"});

    Hello.log("Sending ping to " + to + ".");
    console.log("Sending ping to " + to + ".");

    Hello.start_time = (new Date()).getTime();
    Hello.connection.send(ping);
},

handle_pong: function (iq) {
    var elapsed = (new Date()).getTime() - Hello.start_time;
    Hello.log("Received pong from server in " + elapsed + "ms.");
    console.log('Received pong from server in " + elapsed + "ms.');     
    localStorage.setItem("hello", JSON.stringify(Hello));
    return false;
    }
};

这里是 chat.js

var Hello = {
conn: null
};

$(document).ready(function(e) { 
    Hello = JSON.parse(localStorage.getItem("hello"));
    $('#input3').bind('click', 
    Hello.connection.send("someStanza"))});

在线 Hello = JSON.parse(localStorage.getItem("hello"));我尝试恢复对象。

下面的 2 行我调用 Hello.connection.send。但是,很明显我无法正确传递和恢复 Hello 对象。例如,在 Google Chrome JavaScript 调试器中,我在该行收到一条错误消息,指出 "Uncaught TypeError: undefined is not a function",我想说这基本上意味着 Chrome JS 引擎无法在 Hello 对象中找到任何 connection.send 成员。

这留下了两个选择。我正在尝试做的事情(传递不是原始数据类型的对象)在我做的方式中是不可能的。或者,我这样做的方式有可能,只是我没有看到其他一些错误/问题。

如果可能,我做错了什么?

如果不能以这种方式传递非原始数据类型,我还能怎么做?

希望我说得足够清楚,以便理解,

谢谢,兄弟,

克里斯

【问题讨论】:

    标签: javascript jquery json html local-storage


    【解决方案1】:

    一种解决方法是 toString 函数,然后将其存储在 localStorage 中。然后,当您从 localStorage 检索对象时,您 eval 函数。这是一个演示的快速演示(它非常愚蠢,可以根据您的需要进行优化/增强......):

    http://jsfiddle.net/nmef7utv/

    function pack(obj){
        var packedObj = {};
        for (key in obj) {
    
            // If obj property is a function, toString() it.
            if (obj[key] && obj[key].constructor === Function) {
                packedObj[key] = obj[key].toString();
            } else {
                packedObj[key] = obj[key];
            }
        }
    
        return JSON.stringify(packedObj);
    }
    
    function unpack(obj) {
        // Temporary variable to hold eval'd func, if needed
        var temp;
    
        // Parse obj to loop
        obj = JSON.parse(obj);
    
        for (key in obj) {
            if (typeof obj[key] === "string") {
                eval('temp =' + obj[key]);
    
                // Assign eval'd function
                obj[key] = temp;
            } else {
                obj[key] = obj[key];
            }
        }
        return obj;
    }
    

    在小提琴中,我有:

    // Packed Item
    localStorage.setItem('test', pack(Hello));
    
    // Unpack
    testObj = unpack(localStorage.getItem('test'));
    testObj.handle_pong();
    

    希望对您有所帮助!

    【讨论】:

    • 好主意,但是“eval('temp =' + obj[key]);”似乎会导致代码注入。我真的不认为通过类定义是一个好主意。我认为应该只传递普通数据。
    • 我绝对听到了,@wander。不过,我认为这取决于情况。过去,如果有的话,我很少考虑使用eval(除了可能评估ajax响应)-但后来我读到了几个例子,其中Bing和Google使用localStorage(w / eval)进行缓存从 JavaScript 到 CSS,甚至是 HTML(和图像),应有尽有。真的很酷的东西,否则没有评估是不可能的。虽然肯定有代码注入的机会,但我认为对 eval 聪明(或更重要的是,不要误用 eval)更重要。不过,这也是我的看法:)
    • 嘿@user2606742,eval 调用不应导致闪烁。代码注入通常是指第三方(通常是恶意成员)向您的页面添加(或注入)脚本的术语。例如,假设您的聊天室“打包”了所有消息(我知道,这是一个疯狂的想法......)并且您聊天室的恶意用户意识到了这一点。他们可以发送这样的消息:“(function(){alert('大家好。很高兴见到你!');location.href ='//mysite.com'}())”以及何时(否则正常message) 进行了评估,用户将看到警报,然后看到重定向。
    • 至于为什么它不起作用——我应该提到的一件事是pack 真的,真的很蠢。它假定一个平面对象,所以像Hello.connection = function(){} 这样的东西可以工作,但Hello.connection.send = function(){} 不会(因为send 的嵌套性质......所以它永远不会是toString()ed)为此,你需要更新pack 方法并添加一些递归来打包子属性。希望有帮助!如果您在执行此操作时遇到问题,我很乐意为您提供帮助。
    • Jack Pattishall Jr. 真的很好:) 在你的 html 代码中,你可以这样做,(顺序很重要)。然后在chat.js中你可以直接使用Hello.js中定义的全局对象'Hello'
    猜你喜欢
    • 2011-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多