2013-02-19 89 views
2

我正在從一個陣列項目的方式,只要它不存在,那麼存儲失敗後,在localStorage的JavaScript Array.indexOf()使用本地存儲

var queue = []; 

function moveToQueue(item) { 
    if(queue.indexOf(item) == -1) { 
     queue.push(item); 
     store(); 
    } 
} 

function store() { 
    localStorage.myApp_queue = JSON.stringify(queue); 
} 

頁面加載時,我打電話給我的加載功能。

function load() { 
    if(typeof localStorage.myApp_queue != 'undefined') { 
     queue = JSON.parse(localStorage.myApp_queue); 
    } 
} 

在這一點上,我的界面顯示queue,因爲我已經離開了最後,但如果我嘗試再次添加同一項目中,「queue.indexOf(項目)」失敗。 queue的內容與調用store()/load()方法之前的內容不同。

以下是我的頁面重新加載之前和之後的一些console.log()調用,從空的queue開始。日誌已經被添加到moveToQueue功能開始

function moveToQueue(item) { 
    console.log('adding to queue'); 
    console.log(item); 
    console.log(queue[0]); 
    console.log(queue.indexOf(item)); 
    ... 

初始負載:

adding to queue 
e {id: 1, status: "A", title: "Comcar", $$hashKey: "004", $get: function…} 
undefined 
-1 

adding to queue 
e {id: 1, status: "A", title: "Comcar", $$hashKey: "004", $get: function…} 
e {id: 1, status: "A", title: "Comcar", $$hashKey: "004", $get: function…} 
0 

頁面刷新後 - 我推的項目已經是queue陣列中

adding to queue 
e {id: 1, status: "A", title: "Comcar", $$hashKey: "006", $get: function…} 
Object {id: 1, status: "A", title: "Comcar", $$hashKey: "004"} 
-1 

我在這裏錯過了什麼,localStorageJSON做什麼來改變我的陣列。

我可以看到日誌列出從存儲返回的項目爲「對象」,而原始項目具有「類型」(不太確定)「e」。

如果我使用typeof兩個結果是「對象」

+0

啊,我剛剛意識到一些事情。原來的項目有getter,setter等,它們似乎是真正的javascript對象。那些在localStorage中進行解析/解析的只是簡單的字典/鍵值對!所以我需要阻止他們成爲複雜的對象?我想 – 2013-02-19 12:33:36

+0

我在我的代碼所做的更改,現在它將爲複雜對象的工作太:-) – 2013-02-19 12:58:09

回答

2

我在這裏錯過了什麼,localStorage和JSON做什麼來改變我的數組?

它不會更改您的數組(您的舊數據在卸載頁面時會丟失)。它創建了一個全新的項目對象。如果你現在創建一個看起來就像那些你已經有一個項目,他們仍然是兩個不同的對象,並通過引用(與===indexOf一樣)比較它們將產生false

所以,要麼你將需要改變,沒有新的內置,但舊的被重用你的建築功能,或者需要使用特殊的比較功能,它告訴對象通過其ID例如平等。

+0

好吧,這是有道理的。對象本身是不同的,即使裏面的屬性是相同的。 – 2013-02-19 13:44:45

3

indexOf將通過參考,如果他們是比較對象的值,那麼你的代碼不會對複雜對象的工作(即哈希值,詞典或其他) 。如果使用檢查對象是否相等的函數,則可以使對象甚至可以用於對象。你可以找到這樣的功能在這裏:Object comparison in JavaScript

在我把示例代碼你怎麼能下一節:使用localStorage

  1. 加載和保存數組/對象。
  2. 使您的代碼適用於基元。
  3. 使您的代碼適用於複雜的對象。

加載和localStorage的保存

//Saving array with specific "name" (key for the localStorage) 
function saveArray(name, array) { 
    localStorage.setItem(name, JSON.stringify(array)); 
} 

//Loads specific array and deserialize it. 
function loadArray(name) { 
    return JSON.parse(localStorage.getItem(name)); 
} 

對於原語:

對於原語就可以實現想要的功能,很容易(你的代碼是正確的這類數據):

//This method adds unique elements, which are not already in the array 
Array.prototype.addUnique = function (item) { 
    if (this.indexOf(item) < 0) { 
     this.push(item); 
    } 
}; 

var array = []; 
array.addUnique(1); 
array.addUnique(2); 
array.addUnique(1); 
array.addUnique(3); 
//The current content of the array is [1,2,3] because of the addUnique functionality 
saveArray('myarray', array); 

當您重新加載該頁面使用:

var array = loadArray('myarray'); //[1,2,3] 
array.addUnique(6); 
saveArray('myarray', array); 

現在,在您localStoragearray值將是[1,2,3,6]

對於對象

如果您的陣列中的更復雜的數據,如鍵值對對象使用:

//Code from here: 
//https://stackoverflow.com/questions/1068834/object-comparison-in-javascript 
Object.prototype.equals = function(x) { 
    var p; 
    for(p in this) { 
     if(typeof(x[p])=='undefined') {return false;} 
    } 

    for(p in this) { 
     if (this[p]) { 
      switch(typeof(this[p])) { 
       case 'object': 
        if (!this[p].equals(x[p])) { return false; } break; 
       case 'function': 
        if (typeof(x[p])=='undefined' || 
         (p != 'equals' && this[p].toString() != x[p].toString())) 
         return false; 
        break; 
       default: 
        if (this[p] != x[p]) { return false; } 
      } 
     } else { 
      if (x[p]) 
       return false; 
     } 
    } 

    for(p in x) { 
     if(typeof(this[p])=='undefined') {return false;} 
    } 

    return true; 
} 

Array.prototype.exists = function (item) { 
    var exists = false; 
    this.forEach(function (e) { 
     if (e.equals(item)) { 
     exists = true; 
     return; 
     } 
    }); 
    return exists; 
}; 

Array.prototype.addUniqueObject = function (item) { 
    if (!this.exists(item)) { 
     this.push(item); 
    } 
}; 

var array = []; 
array.addUniqueObject({ foo: 'bar' }); 
array.addUniqueObject({ foo: 'baz' }); 
array.addUniqueObject({ foo: 'bar' }); 
array.addUniqueObject({ foo: 'foobar' }); 
//The current content of the array is [{ foo: 'bar' }, { foo: 'baz' }, { foo: 'foobar' }] because of the addUniqueObject functionality 
saveArray('myarray', array); 

當您重新載入網頁,你可以得到陣列相同的內容使用:

loadArray('myarray'); 
//[{ foo: 'bar' }, { foo: 'baz' }, { foo: 'foobar' }] 

注意

equals添加到Object.prototype的方法,所以您創建的每一個對象都會有這樣的方法!這同樣適用於每個陣列這將有addUniqueaddUniqueObjectequals

如果你不希望這樣,你可以簡單地重構一點這些方法。

+0

'Object.prototype.equals' - 哎喲!不要在* all *對象上創建可枚舉的屬性!你也不應該通過字符串來比較函數。 – Bergi 2013-02-19 12:59:53

+0

是的,它創建它們,這是一個例子 – 2013-02-19 13:00:10

+0

'addUnique'和'addUniqueObject'相同。 – 2013-02-19 13:00:31