2009-11-10 1 views
7
var obj = {} 
obj.__setitem__ = function(key, value){ 
    this[key] = value * value 
} 
obj.x = 2 // 4 
obj.y = 3 // 9 

У JavaScript нет __setitem__, и этот пример явно не работает.JavaScript-эквивалент Python's __setitem__

В питона __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? Все обходные пути помогут вам.

ответ

7

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

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

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

+0

Выглядит хорошо! Не могли бы вы разместить ссылку на страницу там, где это было предложено? – NVI

+0

@NV: Это в некоторой ошибке на bugzilla.mozilla.org. Я не мог найти его с помощью простых поисков, поэтому вам может потребоваться некоторое время, чтобы найти его. –

+0

@NV: Найдено: https://bugzilla.mozilla.org/show_bug.cgi?id=312116 –

10

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

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

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

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

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

1

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

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

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

5

вы можете сделать это (как объекты в 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

Да, я могу. Но Python __setitem__ намного более красивее. – NVI

+2

ok, я переименовал его в '_', может быть больше python-like ... – manji

+1

О, я вижу иронию. Как вы можете реализовать obj.x + = 2 или что-то вроде этого? – NVI

5

В общепринятых версиях 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