2012-03-17 5 views
1

Я сталкиваюсь с причудливой ошибкой при попытке создать объект 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

Объекты на прототипе разделяются между всеми экземплярами –

+0

[эта статья] (http://gotochriswest.com/blog/2011/05/17/forcing-a-constructor-in-javascript/) о принудительном использовании конструкторы могут вас заинтересовать, если вы лично не являетесь единственным потребителем вашего кода (или если вы просто не доверяете себе) – jbabey

ответ

3

Свойство items устанавливается на prototype. Прототип не клонируется при создании объекта, поэтому items то же самое на двух Dict с. Установите items в конструкторе, так что каждый объект имеет свой собственный:

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

Прототипы работать, потому что, когда вы пытаетесь получить доступ свойства объекта, он сначала проверяет собственные свойства объекта, чтобы увидеть, если он содержит его. Если это так, это значение. Если он там не найден, он проверяет прототип. Если его нет, он продолжает перемещаться по цепочке прототипов, пока не найдет свойство. Если он все еще не найден, это приводит к undefined. (Более подробно, see the specification)

+0

> Прототип не клонируется при создании объекта – Matthew

+0

И как раз тогда, когда я думал, что понял прототипы. Э-э! – Matthew

+1

@Matthew: Я добавил немного больше о том, как прототипы * на самом деле * работают. – icktoofay

2

определить класс использовать, попытайтесь переместить определения функций в прототипе, не заменяя прототип объекта, например, так:

 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); 
      }); 
     }; 
5

Вы определения items внутри прототипа что означает, что он будет использоваться всеми экземплярами. Вам нужно установить его внутри функции «конструктор» и удалить его из прототипа.

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

Я создал JS скрипку для вас с полным исходным кодом на http://jsfiddle.net/brunomsilva/zaSY2/.

Смежные вопросы