Чому рамки / бібліотеки JavaScript мають функції, які вже існують у чистому JavaScript?


60

Цікаво, чому рамки / бібліотеки мають власних помічників, хоча вони вже існують.

Візьмемо jQuery і AngularJS . Вони мають свої eachфункції ітератора:

Але ми маємо Array.prototype.forEach.

Аналогічно

Але ми маємо JSON.parse()функцію у ванільному JavaScript.


75
Як хтось, хто пам’ятає погані старі часи веб-розробки, це питання змушує мене плакати.
josh3736

3
@ josh3736 Принаймні, вам досі не потрібно підтримувати IE6 ('Тхо, на щастя, лише в режимі "змусити його працювати, це може виглядати як лайно")
Izkata

12
jQuery.eachі Array.prototype.forEachне рівнозначні.
zzzzBov

3
Що ви повинні запитати у себе: скільки функцій, знайдених зараз у vanillaJS, походить з наборів інструментів, таких як jQ тощо? Відповідь: багато . Це не ставить питання: чому ми все ще їх використовуємо? Навіщо включати jQuery $.each, а не використовувати нативну (і швидше) Array.prototype.forEach?
Elias Van Ootegem

1
@ josh3736 Це нормально, бра
Кроно

Відповіді:


93

Тому що, коли ці бібліотеки були написані, деякі основні браузери не підтримували ці функції. Після написання та використання ці функції неможливо видалити з цих бібліотек, не порушивши багато програм.

(У цьому випадку "основний браузер" означає браузер, який все ще має велику частку ринку, що включає старіші версії браузерів, таких як Internet Explorer, де велика кількість користувачів не обов'язково переходить на останню версію.)


44
$ ('marquee'). кожен (функція () {$ (це) .append ($ ('<bgsound />', {src: "good-answer.mp3"}));});
П’єр Арло

36
@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
Поведінка "core JS" добре визначена та перевірена у всіх браузерах.
Доменіч

2
@Domenic Syntax окрім цього, реалізація JavaScript відрізняється від браузера до браузера. Є властивості, методи, події та функції, які ви знайдете лише в декількох веб-переглядачах, а то й просто в одному.
Кроно

1
Так, браузери мають нестандартні функції. Це не має нічого спільного зі стандартними характеристиками, обговореними в цьому питанні.
Доменіч

8
@Domenic Якщо під "стандартними функціями, обговореними у запитанні" ви маєте на увазі функції Array.prototype.forEachта JSON.parseфункції, швидкий пошук в Google покаже вам, що ви помиляєтесь. JSONОб'єкт не підтримувався в IE7 та forEachне був визначений у деяких версіях Opera. Бібліотеки, такі як jQuery, проте знали про ці обмеження і працювали навколо них за кадром. Тому я думаю, що моя відповідь стоїть.
Кроно

27

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, однак більшість з них Objectє ітерабельним.

З цієї причини багато творців бібліотеки роблять свої функції поліморфними (здатні приймати декілька типів як вхідні дані). Візьмемо код 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);
    }
  }

Масиви (з рідною підтримкою для кожного):

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

Об'єкти, що нагадують масив, включаючи масив (без носія підтримки forEach), String, HTMLElement, об'єкт з дійсним властивістю довжини:

} 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.