使用localStorage后,JavaScript Array.indexOf()失败

时间:2013-02-19 12:32:20

标签: javascript arrays json local-storage indexof

我将项目从一个数组移动到另一个数组,只要它尚不存在,然后将其存储在localStorage

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(item)”失败。 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,两者的结果都是“对象”

2 个答案:

答案 0 :(得分:3)

如果它们是对象,

indexOf将通过引用比较值,因此您的代码将不适用于复杂对象(即哈希,词典或其他)。如果您使用检查对象是否相等的函数,您甚至可以使代码对对象起作用。你可以在这里找到这样的功能:Object comparison in JavaScript

在接下来的部分中,我将尽可能地提供示例代码:

  1. 使用localStorage
  2. 加载并保存数组/对象
  3. 让您的代码适用于基元。
  4. 让您的代码适用于复杂的对象。
  5. 加载并保存在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);
    

    现在,在localStorage array [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被添加到addUnique一样,所以你创建的每个对象都会有这个方法!每个数组都有addUniqueObjectequals和{{1}}。

    如果你不想要这个,你可以简单地重构一下这些方法。

答案 1 :(得分:2)

  

我在这里错过了什么,localStorage和JSON做什么来改变我的阵列?

它不会更改您的阵列(卸载页面时旧的阵列丢失)。它创建了一个全新的项目对象。如果您现在创建的项目看起来与您已有的项目完全相同,那么它们仍然是两个不同的对象,并通过引用进行比较(indexOf===一样)将产生false

因此,您需要更改构造函数,即不构建新构造函数但重复使用旧函数,或者您需要使用特殊的比较函数,例如通过它们的ID来告诉对象。