JavaScript-эквивалент Python __setitem__ - PullRequest
8 голосов
/ 11 ноября 2009
var obj = {}
obj.__setitem__ = function(key, value){
  this[key] = value * value
}
obj.x = 2  // 4
obj.y = 3  // 9

JavaScript не имеет __setitem__, и этот пример, очевидно, не работает.

В Python __ setitem __ работает как:

class CustomDict(dict):
  def __setitem__(self, key, value):
    super(CustomDict, self).__setitem__(key, value * value)

d = CustomDict()
d['x'] = 2  # 4
d['y'] = 3  # 9

Возможно ли реализовать поведение __setitem__ в JavaScript? Все хитрые обходные пути были бы полезны.

Ответы [ 5 ]

10 голосов
/ 11 ноября 2009

Возможно ли реализовать поведение __setitem__ в JavaScript?

Нет. В JavaScript нет методов получения / установки произвольных свойств.

В Firefox вы можете использовать геттеры и сеттеры JavaScript 1.5+ для определения x и y свойств, которые возводят их значения в соответствие, например:

var obj= {
    _x: 0,
    get x() { return this._x; },
    set x(v) { this._x=v*v; }
};
obj.x= 4;
alert(obj.x);

но вы должны будете объявить установщик для каждого именованного свойства, которое вы хотите использовать заранее. И это не будет работать кросс-браузер.

7 голосов
/ 11 ноября 2009

Нет, но есть планы по поддержке аналогичной функции в JavaScript 2. Следующий синтаксис литерала объекта был предложен для Ошибка Mozilla 312116 , и кажется, что это может быть, как это будет сделано для объекта литералы:

({
  get * (property) {
    // handle property gets here
  }
})

Я предполагаю, что set также будет поддерживаться (как set * (property, value) {...}).

5 голосов
/ 17 ноября 2009

В общепринятых версиях Javascript нет истинных сеттеров и геттеров, поэтому, если вы хотите эмулировать эффект, вы должны использовать другой синтаксис. Для свойства obj.x использование obj.x() для доступа к значению свойства и obj.x(123) для установки значения выглядит довольно удобным синтаксисом.

Это может быть реализовано так:

// Basic property class
function Property(value) {
   this.setter(value);
}

Property.prototype.setter = function(value) {
   this.value = value * value;
}

Property.prototype.getter = function() {
   return this.value;
}

Property.prototype.access = function(value) {
   if (value !== undefined)
      this.setter(value);
   return this.getter();
}


// generator function to add convenient access syntax
function make_property(value) {
   var prop = new Property(value);
   function propaccess(value) {
      return prop.access(value);
   }
   return propaccess;
}

Теперь свойства, сгенерированные make_property, поддерживают желаемый синтаксис и квадратные значения, которым они назначены:

var obj = {
   x: make_property(2)
};

alert(obj.x()); // 4
obj.x(3);       // set value
alert(obj.x()); // 9
5 голосов
/ 11 ноября 2009

Вы можете сделать это (поскольку объекты в javascript также являются ассоциативными массивами):

var obj = {};
obj._ = function(key, value){
  this[key] = value * value;
}
obj._('x', 2);  // 4
obj._('y', 3);  // 9

alert(obj.x + "," + obj.y); //--> 4,9
1 голос
/ 11 ноября 2009

Я не думаю, что вы можете переопределить оператор [] в текущей версии Javascript. В текущем Javascript объекты являются в основном просто ассоциативными массивами, поэтому оператор [] просто добавляет пару ключ / значение в массив, который является объектом.

Вы можете написать методы, которые устанавливают конкретные значения или даже возводят в квадрат число и добавляют значение как пару ключ / значение, но не перегружая оператор [].

Javascript2 имеет некоторые спецификации для перегрузки операторов, но эта спецификация - MIA.

...