Объект JavaScript с внутренними ссылочными свойствами - PullRequest
0 голосов
/ 19 сентября 2010

Я пытаюсь создать глобальный объект с серией «ведомых» свойств, которые получаются из значения одного «главного» свойства в том же объекте - что-то вроде:

var x = 5;
var myObj = {
    master : 17,
    slave1 : this.master + x,
    slave2 : (this.master / 2.2) + 1,
    slave3 : Math.floor(this.slave2)
    //etc.
};

Я понимаю, что это ужасно неправильно, как есть, но концепция есть. То, что я хотел бы сделать, это чтобы все эти «ведомые» свойства обновлялись по мере обновления myObj.master. Какой самый чистый способ сделать это? Каждое ведомое значение должно быть явно установлено каким-либо обработчиком событий, который срабатывает при изменении myObj.master ...?

Ответы [ 6 ]

4 голосов
/ 19 сентября 2010

Если вы не нацелены на пользователей Internet Explorer, попробуйте использовать геттеры и сеттеры.

var x = 5;
function myObj()
{
    this.master = 17;
    this.getSlave1 = function() {return this.master + x;},
    this.getSlave2 = function() {return (this.master / 2.2) + 1;},
    this.getSlave3 = function() {return Math.floor(this.getSlave2());}
}

myObj.prototype = {
    get slave1() {
        return this.getSlave1();
    },
    get slave2() {
        return this.getSlave2();
    },
    get slave3() {
        return this.getSlave3();
    }
};   

В действии:

window.onload = function()
{
    o = new myObj();
    document.write("Master: "+o.master+"</br>");
    document.write("Slave 1: "+o.slave1+"</br>");
    document.write("Slave 2: "+o.slave2+"</br>");
    document.write("Slave 3: "+o.slave3+"</br></br>");
    o.master = 42;
    document.write("Master: "+o.master+"</br>");
    document.write("Slave 1: "+o.slave1+"</br>");
    document.write("Slave 2: "+o.slave2+"</br>");
    document.write("Slave 3: "+o.slave3+"</br>");
}

производит вывод:

Master: 17
Slave 1: 22
Slave 2: 8.727272727272727
Slave 3: 8

Master: 42
Slave 1: 47
Slave 2: 20.09090909090909
Slave 3: 20

Этот код никогда не будет работать в любой версии Internet Explorer, в прошлом, настоящем или будущем.Однако к ведомым значениям все еще можно получить доступ с помощью функций getSlaveX().

2 голосов
/ 19 сентября 2010

Ответ Дэвида - один из вариантов, но если вы хотите кэшировать результаты, а не пересчитывать их каждый раз, сделайте это наоборот:

var x = 5;
var myObj = {
    setMaster: function(val) {
        this.master = val;
        this.slave1 = this.master + x;
        // ...
    }
};

myObj.setMaster(17);
2 голосов
/ 19 сентября 2010

Возможно, вам лучше всего использовать функции.

var x = 5;
var myObj = {
    master : 17,
    slave1 : function() { return this.master + x },
    slave2 : function() { return (this.master / 2.2) + 1 },
    slave3 : function() { return Math.floor(this.slave2()); }
    //etc.
};

var example = myObj.slave3();
1 голос
/ 19 сентября 2010

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

var x = 5;

function MyObj(master) {
  this.master = master;
  this.slave1 = this.master + x,
  this.slave2 = (this.master / 2.2) + 1,
  this.slave3 = Math.floor(this.slave2)
}

var myObj = new MyObj(17);

В приведенном выше примере я использую аргумент master и ссылку на глобальное свойство x,если у вас нет x, доступного в этой области, вы также можете предоставить аргумент для него.

Вы также можете построить свой объект в несколько шагов:

var myObj = {
    master : 17
}, x = 5;

myObj.slave1 = myObj.master + x;
myObj.slave2 = (myObj.master / 2.2) + 1;
myObj.slave3 = Math.floor(myObj.slave2);
0 голосов
/ 19 сентября 2010

Вы можете смоделировать геттеры, используя valueOf и toString, но это немного громоздко.

function makeValueOf(fn) {
    return {
        valueOf: fn,
        toString: fn
    };
}

function makeObj(master, x) {
    var self = {};

    self.master = master;
    self.slave1 = makeValueOf(function () { return self.master + x; });
    self.slave2 = makeValueOf(function () { return self.master / 2.2 + 1; });
    self.slave3 = makeValueOf(function () { return Math.floor(self.slave2); });

    return self;
}

var myObj = makeObj(6, 2);
alert(myObj.slave1 + 5); // 13
0 голосов
/ 19 сентября 2010

Вы не хотите выставлять рабов и позволять им быть настроенными, так как это сотрет их связь с мастером.Так что они должны быть частными.

var x = 5;
var MyObject = function() {
    var master = 17;
    this.setMaster = function(newMaster) {
        master = newMaster;
    };
    this.getMaster = function() {
        return master;
    };
    var slaves = {
        slave1 : function() { return master + x },
        slave2 : function() { return (master / 2.2) + 1 },
        slave3 : function() { return Math.floor(this.slave2()) }
    };
    this.getSlave = function(slave) {
        return slaves[slave]();
    };
};

var o = new MyObject();
o.getSlave("slave1"); // 22
o.getSlave("slave3"); // 8
o.setMaster(3);
o.getSlave("slave1"); // 8
o.getSlave("slave3"); // 2
...