0

私は、さまざまなブラウザのさまざまなライブラリからisPlainObject関数のテストを行ってきました。

さまざまなオブジェクトでテストされている4つの異なる(コード単位の)isPlainObject関数があります。

  • jquery
  • lodash
  • ユーティリティ(私が取り組んでいるライブラリ)
  • 代替案、以下のコメントで提案

上記の4つすべてが、Chromev23.0.1271.95からChromev25.0.1364.160、FireFox v 19.0、Opera v12.14までの違いを示していますが、ユーティリティは、すべてのブラウザでこれらのオブジェクトに対して少なくとも同じfalseの応答を返します。

Chromeで実行した場合のjsfiddleでのテスト

Failed to agree: JSON - jquery: true - utility: false - lodash: true - alt: false
Failed to agree: Math - jquery: true - utility: false - lodash: true - alt: false
Failed to agree: top - jquery: false - utility: false - lodash: true - alt: true
Failed to agree: parent - jquery: false - utility: false - lodash: true - alt: true
  • ルーチンはオブジェクトがプレーンであると見なし、falseはプレーンではないと考えることはtrueです。

編集:私はすべてのルーチンが次の同様の基準を使用していると信じています:

jqueryの状態
オブジェクトがプレーンオブジェクト(「{}」または「新しいオブジェクト」を使用して作成されたもの)であるかどうかを確認します。

lodashstates
指定された値がObjectコンストラクターによって作成されたオブジェクトであるかどうかを確認します。

ホストオブジェクトは「{}」または「新しいオブジェクト」を使用して構築されたオブジェクトと同じではないことを理解しているので、私の質問は、ホストオブジェクトをプレーンオブジェクトとしてカウントする必要があるかどうかです。

現在、ユーティリティは一貫しており、そうではないと言っていますが、他のルーチンは、異なるブラウザ上のホストオブジェクトに対して異なる結果をもたらします。

編集:結果の正確さは私にとって最も重要な要素であり、パフォーマンスは二次的な考慮事項です。

3つのライブラリのパフォーマンス結果と推奨される代替案はjsperfで入手できます。

編集:これはユーティリティライブラリ関数であるため、コードを検索する必要はありません。

defineProperty(utility, "isPlainObject", {
    value: (function () {
        var o = {};

        return function (obj) {
            try {
                return utility.isObject(obj) && getPrototypeOf(obj).isPrototypeOf(o);
            } catch (e) {
                return false;
            }
        };
    }())
});
4

1 に答える 1

1

上記の3つはすべて、FireFoxv19.0およびOperav12.14で実行するとテストに合格します。

いいえ、少なくともOperaでは、フィドルのテストwindow.screenMath、、、、、、、、、、およびで失敗JSONします。DOMErrorLSParserFilterDOMImplementationLSwindow.operaSVGExceptiondocument.implementation

これはChrome/Chromiumのバグですか?

何?その異なる関数は異なる結果を返しますか?いいえ。

そして、4つのオブジェクトのそれぞれについて、正しい結果はどうあるべきですか(どの関数が最も正確であるかを判断できるように)?

「正しい」をどのように定義しましたか?「プレーンオブジェクト」をどのように定義しましたか?

3つのルーチンすべてが次の基準を使用していると思います。

オブジェクトがプレーンオブジェクト(「{}」または「新しいオブジェクト」を使用して作成されたもの)であるかどうかを確認します。

不一致が発生したオブジェクトは「作成」されないため、これはほとんど有用な基準ではありません。それらは、たまたま存在するホストオブジェクト(またはネイティブオブジェクト)です。

それでも、これらの関数が使用する基準を比較することはできます。

  • jQueryは非常に奇妙です。ソースコードはgithubで読むことができます。つまり、[[Class]]がのいずれでもBoolean Number String Function Array Date RegExp Errorない、真のプロパティを持たない、それ自体を指すプロパティnodeNameを持たない、プロパティを持たない、またはのプロパティが独自のプロパティを持つオブジェクトまたは関数。windowconstructorprototypeconstructorisPrototypeOf

    彼らはクロスブラウザサポートのためにこれを行っているようですが、ご覧のとおり、プレーンオブジェクトではないと予想される場合には失敗します。

  • ユーティリティは少しわかりにくいですが、チェック自体は単純です。[[Class]]がObjectであり、プロトタイプがであるオブジェクトObject.prototype(つまり、プロトタイプにが降伏するメソッドisPrototypeOfがあるオブジェクト)。true{}

  • LodashにはjQueryのような奇妙な点がいくつかありますが、それほど難しくはありません。githubでソースを読むことができます。最初にオブジェクトタイプをチェックし、nullではないかどうかをチェックし、次にメソッドが存在する場合はそれをObject.prototype経由getPrototypeOf(getPrototypeOf(…))valueOfます。見つかった場合は、オブジェクトまたはそのプロトタイプのいずれかがそのObject.prototypeオブジェクトである必要があり、オブジェクトであってはなりませんArguments。見つからなかった場合は、ここでは説明しないシムにフォールバックします。

    これらはすべてObject.prototype、メソッドを提供しないブラウザーで、異なるオブジェクトを使用して、異なる環境(iframeなど)からのプレーンオブジェクトの検出をサポートするために行われますgetPrototypeOf

  • 代替」実装:これは、オブジェクトのプロトタイプがnull(ただし明示的に除外Object.prototypeされる)またはでObject.prototypeあり、[[Class]]値がであるかどうかをテストしますObject

ホストオブジェクトはプレーンオブジェクトとしてカウントする必要がありますか?

多分。それは常にあなたのユースケースに依存します…</p>

  • それが作成されたように振る舞うnew Object

    次に、getPrototypeOf(obj) == Object.prototype問題ないはずです(クロスフレームオブジェクトをサポートする必要がない場合)。Mathおよびオブジェクトは、このJSON要件を満たします。

  • プロトタイプに干渉する列挙可能なプロパティはありません

    次にgetPrototypeOf(obj) == null、lodashのように、列挙可能なプロパティを許可するか、手動でチェックすることもできます。これはObject.prototype、たとえば「プレーンオブジェクト」として含まれるようになります。

  • 作成可能new Object

    次に、[[Class]]のチェックを追加して、、などのネイティブオブジェクト、および実装固有のクラスを持つすべてのホストオブジェクトObjectを除外します。それらがテストする関数で合格することを本当に期待しますか?また、他のテストに合格した場合、それらは大混乱を引き起こしますか?JSONMathArgumentsisPlainObject

「何を言う?」も参照してください。niftysnippets.org(TJCrowderによるブログ)

于 2013-03-10T13:52:57.467 に答える