Подтвердить что ты не робот

Параметры функциональных возможностей по умолчанию в javascript

Я играю с некоторыми функциями EcmaScript 2015, и я должен сказать, что спецификация довольно трудно понять.

Я полностью понимаю, что этот код должен вызывать ошибку:

(function(a = b, b = 1) { })();

И я знаю, что значение по умолчанию может использовать внешнюю область:

(function() {
  let c = 1;
  return (function(a = c) { return a === 1; })();
})();

Но я не понимаю, почему эти примеры не хороши:

(function() {
  let a = 1;
  (function(a = a) { })();
})();

(function() {
  let b = 1;
  (function(a = b, b = 2) { })();
})();

Мой Chrome 59.0.3071.115 throws ReferenceError, эта переменная не определена.

Кажется, что Chrome делает некоторую оптимизацию, где создается только одна область, где все параметры установлены как недоступные, и они добавляются один за другим после их назначения.

Некоторое доказательство этого может быть:

(function(a = () => b, b = 2) { return a() === 2; })();

Это выглядит как недостающая возможность для моего вкуса, и мне интересно, добавляет ли спецификационная сила только 1 область здесь или это только детали реализации v8.

Может кто-нибудь, пожалуйста, укажите мне, чтобы указать в спецификации, которая могла бы прояснить это?

4b9b3361

Ответ 1

Я не понимаю, почему эти примеры не хороши

Поскольку инициализаторы по умолчанию не оцениваются в родительской области, а скорее внутри области функций. Сами параметры уже находятся в области видимости, поэтому вы можете сделать что-то вроде

(function(a = 2, b = a) { console.log(b); }());

Может кто-нибудь, пожалуйста, укажите мне, чтобы указать в спецификации, которая могла бы прояснить это?

Соответствующий раздел §9.2.12 ФункцияDeclarationInstantiation.

Я должен сказать, что спецификация довольно трудно понять.

Да, но это написано для разработчиков двигателей не для программистов. Однако пояснительная записка в основном подтверждает ваше понимание оптимизации

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

Ваши примеры в основном desugar для

(function() {
  let a = arguments[0] !== undefined ? arguments[0] : b,
//                                                    ^ clearly a ReferenceError
      b = arguments[1] !== undefined ? arguments[1] : 1;
  {
  }
})();

(function() {
  let c = 1;
  return (function() {
    let a = arguments[0] !== undefined ? arguments[0] : c;
//                                                      ^ works as you'd think
    {
      return a === 1;
    }
  })();
})();

(function() {
  let a = 1;
  (function() {
    let a = arguments[0] !== undefined ? arguments[0] : a;
//                                                      ^ again clearly a ReferenceError
    {
    }
  })();
})();

(function() {
  let b = 1;
  (function() {
    let a = arguments[0] !== undefined ? arguments[0] : b,
//                                                      ^ still a ReferenceError
        b = arguments[1] !== undefined ? arguments[1] : 2;
    {
    }
  })();
})();

(function() {
  let a = arguments[0] !== undefined ? arguments[0] : () => b,
//                                                          ^ works indeed
      b = arguments[1] !== undefined ? arguments[1] : 2;
  {
    return a() === 2;
  }
})();