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

JavaScript Array.indexOf()在使用localStorage后失败,javascript,arrays,json,local-storage,indexof,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

只要项目不存在,我就将其从一个数组移动到另一个数组,然后将其存储在
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.indexOf(item)”将失败。
queue
的内容与调用
store()/load()
方法之前不同

这里有一些在重新加载页面之前和之后的
console.log()
调用,从一个空的
队列开始。日志已添加到
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 
页面刷新后-我正在推送的项目已在
队列中

adding to queue
e {id: 1, status: "A", title: "Comcar", $$hashKey: "006", $get: function…}
Object {id: 1, status: "A", title: "Comcar", $$hashKey: "004"}
-1
我在这里遗漏了什么,在更改数组时,
localStorage
JSON
做了什么

我可以看到日志将存储返回的项列为“Object”,而原始项的“type”(不太确定)为“e”


如果我使用
typeof
,两者的结果都是“object”

indexOf
将通过引用比较值(如果它们是对象),因此您的代码不适用于复杂对象(即散列、字典或其他)。如果使用检查对象是否相等的函数,您甚至可以使代码对对象起作用。您可以在这里找到这样的函数:

在接下来的部分中,我将介绍示例代码,说明如何:

  • 使用
    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));
    }
    
    对于基本体:

    对于原语,您可以非常轻松地实现所需的功能(您的代码适用于此类数据):

    现在在
    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
    addUniqueObject
    等于
    的每个数组也是如此

    如果你不想这样,你可以简单地重构这些方法

    我在这里遗漏了什么,localStorage和JSON对更改我的阵列做了什么

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


    因此,要么您需要更改构造函数,使其不再生成新的,而是重复使用旧的,要么您需要使用一个特殊的比较函数,例如,通过ID来告诉对象相等性。

    Aah我刚刚意识到一些事情。原始项有getter、setter等,它们似乎是真正的javascript对象。在localStorage中/从localStorage中解析的只是简单的字典/键值对!所以我需要阻止它们成为复杂的物体?我想我对我的代码做了修改,现在它也可以用于复杂的对象:-)
    Object.prototype.equals
    -哎哟!不要在所有对象上创建可枚举属性!此外,您不应该通过函数的字符串化来比较函数。是的,它会创建函数,这与
    addUnique
    addUniqueObject
    的示例相同。谢谢Minko,我将考虑使用localStorage更改存储方式。我发现Bergi更直接地回答了这个问题,好吧,这是有道理的。对象本身是不同的,即使其中的属性相同。
    //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' }]