JavaScriptフレームワーク/ライブラリに、純粋なJavaScriptにすでに存在する関数があるのはなぜですか?


61

フレームワーク/ライブラリは、ネイティブに既に存在しているのに、なぜ独自のヘルパーを持っているのでしょうか。

jQueryAngularJSを見てみましょう。独自のeach反復関数があります。

しかし、我々は持っていArray.prototype.forEachます。

同様に、

しかしJSON.parse()、バニラJavaScriptには関数があります。


75
ウェブ開発の悪い昔を覚えている人として、この質問は私を泣かせます。
josh3736

3
@ josh3736少なくともIE6をサポートする必要はありません(幸いなことに、「動作させる、がらくたのように見える」方法でのみ)
Izkata 14

12
jQuery.eachArray.prototype.forEach同等ではありません。
zzzzBov 14

3
自問すべきことは、jQなどのツールキットに由来する、現在vanillaJSで見つかっている関数の量です。答えは:manyです。これは、なぜ私たちがまだそれらを使用しているのかという疑問を抱いていますか?なぜjQueryを含めて$.each、ネイティブ(より高速)を使用しないのArray.prototype.forEachですか?
エリアスヴァンOotegem 14

1
@ josh3736それは大丈夫です... i.stack.imgur.com/HJs4V.jpg
Crono

回答:


94

これらのライブラリが作成されたとき、いくつかの主要なブラウザはこれらの機能をサポートしていなかったためです。一度作成して使用すると、これらの機能は多くのアプリケーションを壊さずにこれらのライブラリから削除できません。

(この場合、「メジャーブラウザー」とは、依然として市場シェアが大きいブラウザーを意味します。これには、多数のユーザーが必ずしも最新バージョンにアップグレードしないInternet Explorerなどの古いバージョンのブラウザーが含まれます。)


44
$( 'marquee')。each(function(){$(this).append($( '<bgsound />'、{src: "good-answer.mp3"}));});
ピエールアラード14

37
@dirkk最近のブラウザがサポートしていないわけではありません。誰もが最近のブラウザを使用している視聴者がいるほど幸運ではないということです。
ジョージリース14

14
Array.prototype.forEach配列のみを反復処理します-両方のライブラリ反復関数が配列またはオブジェクトを反復処理できます。
JoeG 14

3
これらの関数は、古いブラウザーをサポートし、ライブラリーを呼び出す古いコードをサポートするためにあり、プログラマーは書き直したくありません。IE 6のサポートを終了した場合でも、IEの古代のコピーをサポートする必要があったときに、使用中のJavaScriptがまだ書かれている可能性があります。
マイケルショップシン

6
この関数の多く(jQuery.parseJSON()など)は、ブラウザーがサポートするかどうかを確認し、ブラウザーメソッドに自分自身を設定し、互換性のないブラウザーでのみ代替を使用します!
ヨーゼフ

35

ので異なるブラウザは異なる実装と機能持つ彼らのJavaScriptエンジンで焼いています。同じ「vanilla-JS」コードは、2つの異なるブラウザー、または同じブラウザーの2つの異なるバージョンで異なる方法で実行できます。

人気のあるJSライブラリによって提供される抽象化レイヤーは、これを回避する方法です。舞台裏では、さまざまなブラウザーの容量と制限を回避し、それらの上に統合された使いやすいAPIを提供します。これにより、DOMオブジェクトの取得やJSONデータのフェッチなどの一般的な操作が、一貫性があり、効率的で、ブラウザーに依存しなくなります。

これにより、ブラウザーXまたはYで動作するようにコードを記述する方法ではなく、コードの動作に集中できる開発者の作業が大幅に容易になります。


2
「コアJS」の動作は十分に指定されており、すべてのブラウザーでテストされています。
ドメニック14

2
@Domenic構文は別として、javascriptの実装はブラウザごとに異なります。プロパティ、メソッド、イベント、機能は、ごく一部のブラウザでしか見られない場合があります。
クロノ

1
はい、ブラウザには非標準の機能があります。これは、この質問で説明した標準機能とは関係ありません。
ドメニック14

8
@Domenic「問題の議論標準機能」によって、あなたが意味する場合Array.prototype.forEachJSON.parse機能を、Googleでクイック検索は、あなたが間違っていることが示されます。JSONオブジェクトはIE7ではサポートforEachされておらず、一部のOperaバージョンでは定義されていませんでした。ただし、jQueryなどのライブラリはこれらの制限を認識しており、舞台裏でそれらを回避しました。だから私は私の答えが立っていると思います。
クロノ14

28

1.後方互換性

JavaScriptはECMAScriptの実装です。これらの機能のほとんどはECMAScript 5(ES5)で導入されましたが、市場で十分なシェアを維持している多くの古いブラウザーはこれらの機能をサポートしていません(ECMAScript 5互換性表を参照)。これらの最も顕著なものはIE8です。

通常、ライブラリはネイティブ実装に戻ります。存在しない場合は、独自のポリフィルを使用します。たとえば、AngularJSの実装(angle.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);
    }
  }

配列(ネイティブforEachサポート付き):

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

Array(ネイティブ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
変更後の将来の参照のために、リンクを更新して特定のコミット(たとえば、angle.js L203-257)を指すようにすることができmasterます。
Whymarrh 14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.