2012-04-27 95 views
1

我正在研究一個大量使用JavaScript的應用程序。我試圖包含一些面向對象的做法。在這種嘗試中,我創建了一個基本的類像這樣:反序列化JavaScript對象實例

function Item() { this.init(); } 
Item.prototype = { 
    init: function() { 
    this.data = { 
     id: 0, 
     name: "", 
     description: ""  
    } 
    }, 

    save: function() { 
    alert("Saving..."); 
    $.ajax({ 
     url: getUrl(), 
     type: "POST", 
     data: JSON.stringify(this.data), 
     contentType: "application/json" 
    }); 
    } 
} 

我在我的應用程序創建項目實例,然後將它們保存到本地存儲像這樣:

Item item = new Item(); 
window.localStorage.setItem("itemKey", JSON.stringify(item)); 

在另一頁,或在另一次,我正在從這樣的本地存儲回收該項目:

var item = window.localStorage.getItem("itemKey"); 
item = JSON.parse(item); 
item.save(); 

不幸的是,「保存」功能似乎沒有達到。在控制檯窗口中,有一個錯誤,指出:

* save_Click (匿名函數) 的onclick *

我有一種預感,在「(匿名函數)」是說的控制檯窗口的方式「調用item.save(),但項目是一個匿名類型,所以我試圖訪問一個匿名函數「。我的問題是,我不知道如何再次將「var item」轉換爲Item類實例。有人可以告訴我嗎?

+0

試圖模仿古典模式而不僅僅是使用原型模式有什麼特別的理由嗎? – 2012-04-27 12:45:30

+0

我不知道「原型」模式是什麼。 – 2012-04-27 14:57:11

+0

是的,我的壞。我其實是想說原型繼承習語。 – 2012-04-27 19:17:11

回答

3

簡短的回答:

功能無法序列化成JSON。

說明:

JSON是基於JS文字語法的一個子集跨平臺的序列化方案。情況就是這樣,它只能存儲某些東西。每個http://www.json.org/

  • 對象:一個對象是無序的一組名稱/值對。一個對象以{(左大括號)開始並以}(右大括號)結束。每個名稱後跟:(冒號),名稱/值對由(逗號)分隔。
  • 數組:數組是數值的有序集合。數組以[(左括號)開始,以[]結尾(右括號)。值由(逗號)分隔。
  • 值:值可以是雙引號或數字,或者true或false或null,或者對象或數組中的字符串。這些結構可以嵌套。

函數無法序列化爲JSON,因爲另一個非JS平臺將無法反序列化並使用它。請考慮相反的例子。假設我在我的服務器上有一個包含屬性和方法的PHP對象。如果我使用PHP的json_encode()對該對象進行序列化,並且方法包含在輸出中,那麼我的JavaScript如何能夠解析和理解方法中的PHP代碼,更不用說使用這些方法了?

您在生成的JSON中看到的內容是您所使用平臺上功能的toString()值。對於序列化的任何不適合JSON的內容,JSON serilizer將調用toString()

我相信你的解決方案是停止在JSON /本地存儲中存儲實例。相反,保存您需要時重新設置爲新實例的實例的相關數據。

+0

OP沒有[嘗試]存儲實例,也沒有任何功能。他只想知道如何從他的數據中重新實例化一個項目。 – Bergi 2012-04-27 14:33:04

+1

@Bergi根本不是真的。她明確指出她擁有一個帶有方法的對象實例,試圖對JSON序列化,然後將其反序列化,並在非序列化方面丟失了方法。我提出的解決方案可能沒有完全解決如何將JS對象序列化爲方法,但我清楚地說明了她的方法有什麼問題,並提出了我認爲是更好的方法。 – JAAulde 2012-04-27 14:47:04

+0

啊,我明白了。我曾看過ajax函數。 – Bergi 2012-04-27 14:56:30

0

您只能在DOMstorage(cookie,urlparams ...,需要通過JSON.stringify/JSON.parse需要[de]序列化的所有東西)中存儲普通對象。所以當你發送ajax數據時你做了什麼

ajaxsend(this.data); 

也適用於字符串序列化。您只能存儲數據,而不是實例屬性(如原型,構造函數等)。所以使用

savestring(JSON.stringify(item.data)); 

這是可能的,因爲item.data是這樣一個普通的對象。當恢復它時,你只會得到那個普通的數據對象。你的情況很容易重建從純數據的Item實例,因爲你的項目在公共區域提供物業持有它們的值(僅):

var item = new Item; 
item.data = JSON.parse(getjsonstring()); 
0

你不能做到這一點,怎麼也可以javascript可能知道項目有保存功能? json不允許函數作爲數據。只是閱讀json規範,你不能保存函數。

你需要做的是在你想要存儲的哈希中創建一個序列化和反序列化方法。這將指定要導出的內容以及在解析相應的json字符串後如何「喚醒」對象。

0

免責聲明

不是全職的時間J.S.開發人員,答案可能有一些小錯誤:

的冗長的解釋

正如@JAAulde提到的,你不能將對象序列化爲JSON,因爲具有的功能,您使用的是不允許的技術它。

許多人忘記或忽略在應用程序中使用的對象可能與從存儲器中保存/恢復的對象不完全相同。

短&快速回答

既然你已經在你的對象的數據成員封裝成一個單一的領域, 你可能想嘗試這樣的事:

// create J.S. object from prototype 
Item item = new Item(); 

// assign values as you app. logic requires 
item.data.name = "John Doe"; 
item.data.description = "Cool developer, office ladies, love him"; 

// encoded item into a JSON style string, not stored yet 
var encodedItem = JSON.stringify(item.data) 

// store string as a JSON string 
window.localStorage.setItem("itemKey", encodedItem); 

// do several stuff 

// recover item from storage as JSON encoded string 
var encodedItem = window.localStorage.getItem("itemKey"); 

// transform into J.S. object 
item.data = JSON.parse(encodedItem); 

// do other stuff 

乾杯。

1

我知道這個問題已經回答了,但是我偶然偶然發現了這個問題,並且想分享一個解決這個問題的方法,如果有人感興趣的話。

,而不是這樣做:

var item = window.localStorage.getItem("itemKey"); 
item = JSON.parse(item); 
item.save(); 

做這樣的事情:

// get serialized JSON 
var itemData = window.localStorage.getItem("itemKey"); 
//instantiate new Item object 
var item = new Item(); 
// extend item with data 
$.extend(item, JSON.parse(itemData)); 

// this should now work 
item.save(); 

這將工作,只要你想調用的函數(即,保存())爲原型而不是實例方法(通常是這種情況,OP的原始問題的確是這種情況。

$.extend方法是一種jQuery的實用方法,但它是微不足道的滾動自己的。