Синтаксис вопросительного знака от CoffeeScript без CoffeeScript

CoffeeScript имеет такой синтаксический сахар:

item.getFoo?().fooParam?.bar

Это переводит в длинный эквивалент javascript с проверками getFoo==null и fooParam==null. Вопрос в следующем: есть ли способы использовать этот синтаксис в javascript vanilla с библиотекой/переводчиком/компилятором, отличным от CoffeeScript? Мы используем Traceur в нашем проекте, но у него нет такого синтаксиса, потому что он не соответствует требованиям ES6 (хотя я этого и желаю). Может быть, каким-то образом реализовать его в вилке Traceur?

Ответ 1

Если вам не нужна точная семантика CoffeeScript, вы можете немного обмануть:

return item.getFoo ? (item.getFoo().fooParam || {}).bar : undefined;

Здесь есть несколько трюков.

  • Тернарный оператор используется для проверки правдоподобности item.getFoo
  • Если fooParam отсутствует, ложно или отсутствует, мы заменяем его пустым объектом. CoffeeScript вылетел бы здесь.
  • Мы возвращаем значение bar независимо от того, существует ли оно. Если он существует, вы получаете нужное значение. Если он не существует, но fooParam установлен, вы получаете undefined. Если он не существует, потому что fooParam был undefined, и мы вернулись к {}, вы все равно получите undefined.

Вы можете написать некоторые помощники, если троичный оператор мешает:

function defaultObject(input) { // A helper to put somewhere
    return input || {};
}

return defaultObject((item.getFoo || defaultObject)().fooParam).bar;

Это даже сложнее: defaultObject будет возвращать {} при вызове с getFoo, поэтому вам не нужен тройной оператор вокруг вызова функции. Если fooParam не является правдивым, defaultObject возвращает другой пустой объект, исключая необходимость в другом ||. Если fooParam является правдивым, defaultObject ведет себя как функция идентификации и возвращает его.

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

Ответ 2

У меня был такой же вопрос в последнее время, и я приехал сюда, надеясь на лучшее решение, чем мой нынешний. Если вы делаете это часто, проще сделать функцию для этого:

var qm = function(arg) {
  if (arg instanceof Object) return arg;
  return function(){};
};

Затем, чтобы использовать его, вы обертываете свои объекты в нем, чтобы убедиться, что ошибка не поднята. Он начинает выглядеть уродливым, если в строке

есть много q uestion m
qm(qm(item.getFoo)().fooParam).bar