2013-02-19 70 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