Почему фреймворки / библиотеки JavaScript имеют функции, которые уже существуют в чистом JavaScript?

61

Интересно, почему у фреймворков / библиотек есть свои помощники, хотя они уже существуют изначально.

Давайте возьмем jQuery и AngularJS . У них есть свои собственные eachфункции итератора:

Но у нас есть Array.prototype.forEach.

По аналогии,

Но у нас есть JSON.parse()функция в ванильном JavaScript.

Джихад Турхан
источник
75
Как человек, который вспоминает старые дурные времена веб-разработки, этот вопрос заставляет меня плакать.
josh3736
3
@ josh3736 По крайней мере, вам все еще не нужно поддерживать IE6 (хотя, к счастью, только «
заставь
12
jQuery.eachи Array.prototype.forEachне эквивалентны.
zzzzBov
3
Вы должны спросить себя: сколько функций, найденных в vanillaJS сейчас, созданы из таких инструментов, как jQ и тому подобное? Ответ: много . Отсюда возникает вопрос: почему мы до сих пор их используем? Зачем включать jQuery $.each, а не использовать нативный (и быстрее) Array.prototype.forEach?
Элиас Ван Отегем
1
@ josh3736 Все в порядке, брат ... i.stack.imgur.com/HJs4V.jpg
Кроно,

Ответы:

94

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

(В данном случае «основной браузер» означает браузер, который все еще имеет большую долю рынка, который включает в себя более старые версии браузеров, таких как Internet Explorer, где большое количество пользователей не обязательно обновляется до последней версии.)

Горт Робот
источник
44
$ ('marquee'). each (function () {$ (this) .append ($ ('<bgsound />', {src: "good-answer.mp3"}));});
Пьер Арло
37
@dirkk Не то, чтобы последние браузеры не поддерживали его. Дело в том, что не всем повезло иметь аудиторию, которая использует недавний браузер.
Джордж Райт
14
Array.prototype.forEachвыполняет итерацию только над массивами - обе функции библиотеки итератора могут выполнять итерацию над массивами или объектом.
JoeG
3
Функции существуют для поддержки старых браузеров и для поддержки старого кода, который вызывает библиотеку, и программист не хочет переписывать. Даже если вы отказались от поддержки IE 6, у вас, вероятно, все еще есть написанный JavaScript, когда вам нужно было поддерживать древние копии IE.
Михаил Шопсин
6
Многие из этих функций (например, jQuery.parseJSON ()) просто проверяют, поддерживает ли браузер его, а затем настраиваются на метод браузера и используют альтернативу только в несовместимых браузерах!
Йозеф
35

Потому что разные браузеры имеют разные реализации и функции, встроенные в их движок JavaScript. Один и тот же код "vanilla-JS" может работать по-разному в двух разных браузерах или даже в двух разных версиях одного и того же браузера.

Уровень абстракции, предоставляемый популярными библиотеками JS, позволяет обойти это. За кулисами он работает с различными возможностями и ограничениями браузеров и предлагает унифицированный, простой в использовании API поверх них. Это, в свою очередь, позволяет согласованным, эффективным и независимым от браузера обычным операциям, таким как получение объекта DOM или выборка данных JSON.

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

Хроно
источник
2
Поведение «ядра JS» хорошо определено и протестировано во всех браузерах.
Доменик
2
@ Domenic Синтаксис в стороне, реализации JavaScript отличаются от браузера к браузеру. Существуют свойства, методы, события и функции, которые вы найдете только в нескольких браузерах или даже в одном.
Crono
1
Да, в браузерах есть нестандартные функции. Это не имеет ничего общего со стандартными функциями, обсуждаемыми в этом вопросе.
Доменик
8
@Domenic Если на «стандартных функций , рассмотренных в этом вопросе» вы имеете в виду Array.prototype.forEachи JSON.parseфункции, быстрый поиск по Google покажет вам , что вы не правы. JSONобъект не был поддержан в IE7 и forEachне был определен в некоторых версиях Opera. Однако такие библиотеки, как jQuery, знали об этих ограничениях и обходили их за кулисами. Поэтому я думаю, что мой ответ остается в силе.
Crono
28

1. Обратная совместимость

JavaScript - это реализация ECMAScript . Большинство из этих функций были введены в ECMAScript 5 (ES5), однако многие старые браузеры, которые все еще имеют достаточно значительную долю рынка, не поддерживают эти функции (см. Таблицу совместимости ECMAScript 5 ), наиболее заметной из которых является IE8.

Как правило, библиотеки возвращаются к собственной реализации, если она существует, в противном случае они используют собственный полифилл, например, давайте посмотрим на реализацию AngularJS ( angular.js L203-257 ):

function forEach(obj, iterator, context) {
  var key;
  if (obj) {
    if (isFunction(obj)){
      for (key in obj) {
        // Need to check if hasOwnProperty exists,
        // as on IE8 the result of querySelectorAll is an object without a hasOwnProperty function
        if (key != 'prototype' && key != 'length' && key != 'name' && (!obj.hasOwnProperty || obj.hasOwnProperty(key))) {
          iterator.call(context, obj[key], key);
        }
      }
    } else if (obj.forEach && obj.forEach !== forEach) {
      obj.forEach(iterator, context);
    } else if (isArrayLike(obj)) {
      for (key = 0; key < obj.length; key++)
        iterator.call(context, obj[key], key);
    } else {
      for (key in obj) {
        if (obj.hasOwnProperty(key)) {
          iterator.call(context, obj[key], key);
        }
      }
    }
  }
  return obj;
}

Следующие строки проверяют, forEachсуществует ли метод на объекте и является ли он версией AngularJS или нет. Если нет, он использует уже указанную функцию (нативная версия):

} else if (obj.forEach && obj.forEach !== forEach) {
  obj.forEach(iterator, context);
}

2. Удобство

В нативном JavaScript Array.prototype.forEachэто метод, эксклюзивный для экземпляра Array, но большинство Objectany тоже итерируемо.

По этой причине многие создатели библиотек делают свои функции полиморфными (способными принимать в качестве входных данных несколько типов). Давайте возьмем приведенный выше код AngularJS и посмотрим, какие входные данные он принимает:

Функции :

if (isFunction(obj)){
  for (key in obj) {
    // Need to check if hasOwnProperty exists,
    // as on IE8 the result of querySelectorAll is an object without a hasOwnProperty function
    if (key != 'prototype' && key != 'length' && key != 'name' && (!obj.hasOwnProperty || obj.hasOwnProperty(key))) {
      iterator.call(context, obj[key], key);
    }
  }

Массивы (с собственной поддержкой forEach):

} else if (obj.forEach && obj.forEach !== forEach) {
  obj.forEach(iterator, context);

Подобные массиву объекты, включая Array (без встроенной поддержки forEach), String, HTMLElement, Object с допустимым свойством длины:

} else if (isArrayLike(obj)) {
  for (key = 0; key < obj.length; key++)
    iterator.call(context, obj[key], key);

Объекты:

} else {
  for (key in obj) {
    if (obj.hasOwnProperty(key)) {
      iterator.call(context, obj[key], key);
    }
  }
}

Заключение

Как вы можете видеть, AngularJS будет перебирать практически любой объект JavaScript, хотя он работает так же, как и нативная функция, он принимает гораздо более разные типы ввода и, таким образом, является допустимым дополнением к библиотеке, а также способом вызова функций ES5. в устаревших браузерах.

Джордж Райт
источник
2
Возможно, вы захотите обновить свою ссылку, чтобы она указывала на конкретный коммит (например, angular.js L203-257 ) для использования в будущем после masterвнесения изменений.
Whymarrh