Самостоятельные ссылки в объектных литералах / инициализаторах - PullRequest
613 голосов
/ 06 января 2011

Есть ли способ заставить что-то вроде следующего работать в JavaScript?

var foo = {
    a: 5,
    b: 6,
    c: this.a + this.b  // Doesn't work
};

В текущей форме этот код явно выдает ошибку ссылки, так как this не ссылается на foo.Но - это , есть ли способ, чтобы значения в свойствах литерала объекта зависели от других объявленных ранее свойств?

Ответы [ 23 ]

0 голосов
/ 28 августа 2018

Другой подход, чтобы сделать вещи немного проще и не определять новые функции в объекте , состоит в том, чтобы сохранить исходный объект с его свойствами, создать второй объект с динамическими свойствами, которые используют первый Свойства объекта, а затем объединить, используя spread .

Итак:

1010 * Объект *

var foo = {
    a: 5,
    b: 6,
};

Объект 2

var foo2 = {
    c: foo.a + foo.b
};

Объединить

Object.assign(foo, foo2);

или

foo = {...foo, ...foo2};

Результат foo:

{ 
  "a":5,
  "b":6,
  "c":11
}

Все в пределах одного и того же js, никаких новых функций внутри объекта, только с использованием назначений или расширений.

0 голосов
/ 19 июня 2018

Примечание: В этом решении используется Typescript (вы можете использовать vanilla JS, в которую TS при необходимости компилирует)

class asd {
    def = new class {
        ads= 'asd';
        qwe= this.ads + '123';
    };

    // this method is just to check/test this solution 
    check(){
        console.log(this.def.qwe);
    }
}

// these two lines are just to check
let instance = new asd();
instance.check();

Здесь мы использовали выражения класса для получения литерального интерфейса вложенного объекта, который нам нужен. ИМХО это следующая лучшая вещь, чтобы иметь возможность ссылаться на свойства объекта во время создания.

Главное, на что нужно обратить внимание, при использовании этого решения у вас точно такой же интерфейс, какой был бы у литерала объекта. И синтаксис довольно близок к самому литералу объекта (против использования функции и т. Д.).

Сравните следующее

Решение, которое я предложил

class asd {
    def = new class {
        ads= 'asd';
        qwe= this.ads + '123';
    };

Решение, если бы объектных литералов было бы достаточно

var asd = {
    def : {
        ads:'asd',
        qwe: this.ads + '123';, //ILLEGAL CODE; just to show ideal scenario
    }
}

Другой пример

Здесь, в этом классе, вы можете комбинировать несколько относительных путей между собой, что невозможно с литералом объекта.

class CONSTANT {
    static readonly PATH = new class {
        /** private visibility because these relative paths don't make sense for direct access, they're only useful to path class
         *
         */
        private readonly RELATIVE = new class {
            readonly AFTER_EFFECTS_TEMPLATE_BINARY_VERSION: fs.PathLike = '\\assets\\aep-template\\src\\video-template.aep';
            readonly AFTER_EFFECTS_TEMPLATE_XML_VERSION: fs.PathLike = '\\assets\\aep-template\\intermediates\\video-template.aepx';
            readonly RELATIVE_PATH_TO_AFTER_EFFECTS: fs.PathLike = '\\Adobe\\Adobe After Effects CC 2018\\Support Files\\AfterFX.exe';
            readonly OUTPUT_DIRECTORY_NAME: fs.PathLike = '\\output';
            readonly INPUT_DIRECTORY_NAME: fs.PathLike = '\\input';
            readonly ASSETS_DIRECTORY_NAME: fs.PathLike = '\\assets';
        };
    }
}
0 голосов
/ 13 февраля 2018

Добавление варианта, так как я не видел этого точного сценария. Если вы не хотите обновить c при обновлении a или b, то ES6 IIFE работает хорошо.

var foo = ((a,b) => ({
    a,
    b,
    c: a + b
}))(a,b);

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

  let processingState = ((indexOfSelectedTier) => ({
      selectedTier,
      indexOfSelectedTier,
      hasUpperTierSelection: tiers.slice(0,indexOfSelectedTier)
                             .some(t => pendingSelectedFiltersState[t.name]),
  }))(tiers.indexOf(selectedTier));

Поскольку мне нужно установить свойство для indexOfSelectedTier, и мне нужно использовать это значение при установке свойства hasUpperTierSelection, я сначала вычисляю это значение и передаю его в качестве параметра IIFE

...