Как мне обнаружить / запасной вариант, если в браузере нет синтаксиса распространения (… Обозначения в функциях) Поддержка?

#javascript #function #cross-browser #compatibility #spread-syntax

#javascript #функция #кроссбраузерность #совместимость #синтаксис распространения

Вопрос:

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

   function debug (mode, string, ...params) {
    if (debug_enabled amp;amp; window.console) {
      console.log(mode ": " string "(",...params,");");
    }
  }
  

К сожалению, эта функциональность не поддерживается в Internet Explorer и более старых версиях других браузеров. Здесь есть дополнительная информация о синтаксисе spread и поддержке браузера.

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

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

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

Я надеялся, что у кого-нибудь может быть или знать умный способ обнаружить поддержку синтаксиса spread и исключить части скрипта, если синтаксис spread не поддерживается браузером пользователя. Таким образом, я могу предоставить пользователям старых браузеров все еще функциональный интерфейс, в котором отсутствуют лишь несколько функций. Я искал в Интернете и не смог найти никакого кода, который это делает. Я думаю, что это может быть невозможно из-за того, что это модификация основного синтаксиса, однако я не могу найти ничего, что полностью подтверждало бы, что это так.

Ответ №1:

Хотя возможна проверка того, поддерживает ли браузер spread, а затем загрузка соответствующего скрипта, есть гораздо более простой вариант: интегрируйте такой инструмент, как Babel, в ваш процесс сборки, чтобы автоматически перенести ваш код с синтаксиса ES6 на ES5 автоматически. Например, если вы подключите следующее к Babel:

 function debug (mode, string, ...params) {
  if (debug_enabled amp;amp; window.console) {
    console.log(mode ": " string "(",...params,");");
  }
}
  

Вы получаете

 "use strict";

function debug(mode, string) {
  if (debug_enabled amp;amp; window.console) {
    var _console;

    for (var _len = arguments.length, params = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key  ) {
      params[_key - 2] = arguments[_key];
    }

    (_console = console).log.apply(_console, [mode   ": "   string   "("].concat(params, [");"]));
  }
}
  

Вы можете попробовать демо здесь.

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

Разумеется, Babel не ограничивается только переносом синтаксиса распространения — он может переносить весь современный синтаксис вплоть до ES5 (такой как деструктурирование, распространение объектов, возведение в степень ( ** ) и многие другие).

Тем не менее, обратите внимание, что перенос синтаксиса отличается от новых встроенных функций. Например, Array.prototype.includes это функция ES6, но поскольку это новая функция, а не новый синтаксис, она не будет перенесена — чтобы старые браузеры также понимали новые функции, используйте полизаполнения, например, polyfill.io .

Если вы действительно хотите иметь возможность динамически определять, поддерживает ли текущий клиент синтаксис spread, вы можете использовать new Function , чтобы увидеть, правильно ли проанализирован синтаксис или нет:

 function supportsSpread() {
  try {
    new Function('foo(...params);');
    return true;
  } catch(e) {
    return false;
  }
}

console.log(supportsSpread());  

(но на самом деле для этого нет никаких веских причин)

Комментарии:

1. Большое спасибо! Я думаю, вы хотите сказать, что то, что я пытаюсь сделать с помощью JavaScript, невозможно. Моя текущая разработка для этого проекта включает в себя множество итераций, и я очень заинтересован в том, чтобы время этого цикла было минимальным. Однако, похоже, я могу просто поместить эту часть кода через Babel и оставить ее неясной, и это может быть самым простым решением. И это интересно, что Babel выполняет все сложные переводы, но не делает чего-то, что кажется простым, например, добавление новых функций. Большое спасибо за ваш ответ!

2. У меня есть пара вопросов: 1) В нем есть «использовать строго», однако я думаю, что мне это не нужно. Является ли менее рискованным изменение поведения для включения или исключения этого? 2) При переводе получается более длинный код. Может ли этот перевод негативно повлиять на время выполнения в браузерах, совместимых с ES6?

3. use strict Был автоматически добавлен Babel, я не думаю, что это необходимо, но если в коде нет проблем, которые привели бы к строгому отбрасыванию (например, неявному созданию глобальных переменных), нет никакого вреда в его включении. Да, из-за Babel выполнение кода в браузерах ES6 займет больше времени, но об этом редко стоит беспокоиться.

4. Я думаю, что это альтернативное решение, а не ответ на вопрос. Может быть, добавить это в качестве комментария?

5. @Arashsoft Вопрос — это очень сложная проблема. В ответе можно указать на Y-решение проблемы, с которой мы столкнулись. Я отредактировал решение X из-за снижения, но я действительно надеюсь, что никто его не использует