两个实例包含相同的值

问题描述:

我在尝试创建一个Dictionary对象时遇到了一个奇怪的错误。很基本的东西。但是,当我创建对象的2个实例,然后设置一个值时,它们出现在两者上。我在这里做错了什么?两个实例包含相同的值

function Dict() { } 

Dict.prototype = { 

    items: { }, 

    prop: function(key) { 
    return ':' + key; 
    }, 

    get: function(key, def) { 
    var p = this.prop(key), 
     k = this.items; 

    return k.hasOwnProperty(p) ? k[p] : def; 
    }, 

    set: function(key, value) { 
    var p = this.prop(key); 

    this.items[p] = value; 

    return value; 
    }, 

    count: function() { 
    return Object.keys(this.items).length; 
    }, 

    has: function(key) { 
    var p = this.prop(key); 

    return this.items.hasOwnProperty(p); 
    }, 

    del: function(key) { 
    var p = this.prop(key), 
     k = this.items; 

    if(k.hasOwnProperty(p)) 
     delete k[p]; 
    }, 

    keys: function() { 
    return Object.keys(this.items).map(function(key) { 
     return key.substring(1); 
    }); 
    } 
}; 

var a = new Dict(); 
var b = new Dict(); 

a.set('foo', 'bar'); 

console.log(a.keys()); 
console.log(b.keys()); 
+0

原型上的对象在所有实例之间共享关于强制正确使用的所有实例 – 2012-03-17 00:46:36

+0

[本文](http://gotochriswest.com/blog/2011/05/17/forcing-a-constructor-in-javascript/)如果你个人不是你的代码的唯一消费者(或者你只是不信任你自己),那么构造函数可能会对你感兴趣。 – jbabey 2012-03-17 00:49:53

items属性设置在prototype。原型在创建对象时未被克隆,所以items在两个Dict上是相同的。在构造函数中设置items所以每个对象都有自己:

function Dict() { 
    this.items = {}; 
} 

原型工作,因为当您尝试访问对象的属性,它首先检查对象自身的属性,看看它是否包含它。如果是这样,那就是价值。如果没有找到,它会检查原型。如果它不在那里,它会继续遍历原型链,直到它找到该属性。如果仍未找到,则结果为undefined。 (更多细节,see the specification

+0

>当创建一个对象时,原型没有被克隆 – Matthew 2012-03-17 00:48:31

+0

而且当时我还以为我理解了原型。呃! – Matthew 2012-03-17 00:48:53

+1

@Matthew:我添加了一些关于原型*实际*工作原理的更多细节。 – icktoofay 2012-03-17 00:54:17

定义一个类中使用,请尝试将函数定义为原型而无需更换原型对象,就像这样:

 function Dict() { 
     this.items = {}; 
    } 
    Dict.prototype.prop = function (key) { 
     return ':' + key; 
    }; 
    Dict.prototype.get = function (key, def) { 
     var p = this.prop(key), 
    k = this.items; 

     return k.hasOwnProperty(p) ? k[p] : def; 
    }; 
    Dict.prototype.set = function (key, value) { 
     var p = this.prop(key); 

     this.items[p] = value; 

     return value; 
    }; 
    Dict.prototype.count = function() { 
     return Object.keys(this.items).length; 
    }; 
    Dict.prototype.has =function (key) { 
      var p = this.prop(key); 

      return this.items.hasOwnProperty(p); 
     }; 
    Dict.prototype.del =function (key) { 
      var p = this.prop(key), 
    k = this.items; 

      if (k.hasOwnProperty(p)) 
       delete k[p]; 
     }; 
    Dict.prototype.keys = function() { 
      return Object.keys(this.items).map(function (key) { 
       return key.substring(1); 
      }); 
     }; 

你定义items你的原型中这意味着它将被所有实例共享。您需要将其设置在“构造函数”函数中,并将其从原型中移除。

function Dict() { this.items = []; } 

我在http://jsfiddle.net/brunomsilva/zaSY2/创造了一个JS捣鼓你有完整的源代码。