Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Синхронизация со значением объекта (https://javascript.ru/forum/misc/32660-sinkhronizaciya-so-znacheniem-obekta.html)

kaf 24.10.2012 20:54

Синхронизация со значением объекта
 
так не работает
var a={},b;
a[b]=0;
var c=a[b];
c++;
alert(a[b]);

так работает
var a={},b;
a[b]=0;
var c=[a,b];
c[0][c[1]]++;
alert(a[b]);

можно ли упростить логику синхронизации со значением объекта?

oneguy 24.10.2012 21:17

Можно использовать аксессорные свойства объектов, правда, они не работают в IE<9.
var a={}, b;
a[b]=0;
Object.defineProperty(window, "c", {
  get: function () {
    return a[b];
  },
  set: function (v) {
    a[b]=v;
  },
  enumerable: true
});
c++;
alert(a[b]);

kaf 24.10.2012 21:33

Спасибо, не знал об этом способе.

Правда, мне нужна возможность синхронизации с любым доступным объектом (его значением). А здесь строгая привязка к a[b]

Да и начальство требует IE8+

nerv_ 24.10.2012 22:12

var a={}, b = 'b';
a[b]=0;
a[b]++;
alert(a[b]);

сразу не въехал, что нужно
var a = {};
var c = {};
var b;

a[ b ] = 0;
c[ b ] = a[ b ];
alert( c[ b ] );

только я не понимаю зачем это, если в большинстве случаев достаточно
var a = {};
var c = a;
var b;
a[ b ] = 0;
alert( c[ b ] );

oneguy 24.10.2012 22:22

Цитата:

Сообщение от kaf
Спасибо, не знал об этом способе.

Правда, мне нужна возможность синхронизации с любым доступным объектом (его значением). А здесь строгая привязка к a[b]

Это не проблема. В качестве сеттера и геттера свойства можно использовать любые функции. Я привёл лишь пример использования геттера и сеттера.
Цитата:

Да и начальство требует IE8+
Только что прочитал, что в IE 8 аксессорные свойства можно создать для DOM объектов. window является таким объектом, но почему-то мой код в IE 8 не работает.

kaf 24.10.2012 22:59

nerv_, oneguy Предполагается создать контейнер (массив d для примера), в который можно "подписать" на определенное действие любые "элементы" любых объектов по ссылке.
var a={},b,a1={},b1;
a[b]=0;a1[b1]=1;
var d=[];
d.push([a,b]);d.push([a1,b1]);
for(var i=0;i<d.length;i++){
    d[i][0][d[i][1]]++;
    // или еще что-то
}
alert(a[b]+', '+a1[b1]);

nerv_ 24.10.2012 23:12

это?

oneguy 24.10.2012 23:38

Цитата:

Сообщение от Дзен-трансгуманист (Сообщение 212057)
Ну это вряд ли...
alert(window instanceof Node); // false

Так-то корнем является document, так что разве что через него, и потом, опционально, через with. Но это не наилучшая идея, имхо.

Да нет, в IE 8 в window тоже можно добавлять аксесорные свойства.
Оказывается, дело было в enumerable: true, если это убрать, то в IE 8 работает (в этом нет ошибки согласно спецификации, просто Object.defineProperty в IE 8 реализован нестандартным способом).
Этот пример работает также в IE 8.
var a={}, b;
a[b]=0;
Object.defineProperty(window, "c", {
  get: function () {
    return a[b];
  },
  set: function (v) {
    a[b]=v;
  }
});
c++;
alert(a[b]);

kaf 24.10.2012 23:40

nerv_ Нет. Мне нужен механизм для доступа к актуальным значениям "подписанных элементов", чтобы, например, по таймеру или по команде извне выполнять определенные действия с учетом текущих значений.

oneguy 24.10.2012 23:47

Цитата:

Сообщение от kaf
nerv_, oneguy Предполагается создать контейнер (массив d для примера), в который можно "подписать" на определенное действие любые "элементы" любых объектов по ссылке.

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

kaf 24.10.2012 23:57

oneguy Спасибо. Хотя сейчас и нужна поддержка IE8, со временем эта необходимость может отпасть, т.ч. буду иметь в виду...

oneguy 25.10.2012 00:09

Цитата:

Сообщение от kaf (Сообщение 212084)
oneguy Спасибо. Хотя сейчас и нужна поддержка IE8, со временем эта необходимость может отпасть, т.ч. буду иметь в виду...

Однако в IE 8 можно сделать что-то подобное, используя глобальные переменные с именами типа d0, d1, ..., как в следующем примере.
var a={},b,a1={},b1;
a[b]=0;a1[b1]=1;
Object.defineProperty(window, "d0", {
  get: function () {
    return a[b];
  },
  set: function (v) {
    a[b]=v;
  }
});
Object.defineProperty(window, "d1", {
  get: function () {
    return a1[b1];
  },
  set: function (v) {
    a1[b1]=v;
  }
});
for(var i=0;i<2;i++){
    window["d"+i]++;
    // или еще что-то
}
alert(a[b]+', '+a1[b1]);

kaf 25.10.2012 12:02

oneguy Много глобальных переменных, мне кажется, не есть хорошо. Чуть подправил, получилась основа нужного мне механизма.
function F(){
    this.counter=0;
    var self=this;
    this.bind=bind;
    function bind(a,b){
        var link='link_'+self.counter;
        Object.defineProperty(window, link, {
             get: function () {
                 return a[b];
             },
             set: function (v) {
                 a[b]=v;
             }
        });
        self.counter++;
        return link;
    }
}

var f=new F();
var d=[];

var a={},b;
a[b]=0;
d.push(f.bind(a,b));

var a1={},b1;
a1[b1]=1;
d.push(f.bind(a1,b1));

for(var i=0;i<d.length;i++){
    window[d[i]]++;
    // или еще что-то
}
alert(a[b]+', '+a1[b1]);


Часовой пояс GMT +3, время: 17:28.