0

いくつかのシム/ポリフィル ライブラリを調べたところ、Object.getPrototypeOf. 存在しない場合、それらは使用に失敗し、__proto__それが存在しない場合はobject.constructor.prototype.

それ__proto__は「非標準」であり、方法とは少し異なりObject.getPrototypeOfますが、かなり互換性があることを理解しています。

また、原則として、他の 2 つが存在しない多くの状況では、外部アクセス可能で十分であることも理解していますobject.constructor.prototype(プロトタイプが再割り当てされていない場合)。

私が問題を抱えているのは、次の例です。

    function findPropertyOwner(object, property) {
        var count = 0;

        do {
            if (object.hasOwnProperty(property)) {
                return [object, count];
            }

            object = Object.getPrototypeOf(object);
            count += 1;
        } while (object);

        return undefined;
    }

または

    function instanceOf(object, constructor) {
        while (object) {
            if (object === constructor.prototype) {
                return true;
            }

            object = Object.getPrototypeOf(object);
        }

        return false;
    }

上記のような、いわば「チェーンをたどる」例で、シムがフォールバックするobject.constructor.prototypeと、無限ループという恐ろしい状況に陥ります。

私の質問: および が存在しない環境で上記のコードを実現する方法はありますObject.getPrototypeOf__proto__?

無いような気がしますが、まだ知らない情報があれば調べてみたいと思います。

4

1 に答える 1

0

@squint のコメントに基づいて、私が試した解決策を紹介します。私が知る限り、John Resig のブログObject.getPrototypeOfに基づいて、ライブラリ間で一般的であるように思われる一般的なシムを作り直しました。

クロスブラウザ実装

明らかな問題は、次のようになります: Object.getPrototypeOf を、ほとんどのブラウザーがまだ実装していない場合、どのように使用を開始すればよいでしょうか? それまでの間、何らかの形式の互換性のために、次のコードのようなものを使用できます。

if (typeof Object.getPrototypeOf !== "function") {
    if (typeof "test".__proto__ === "object") {
        Object.getPrototypeOf = function (object) {
            return object.__proto__;
        };
    } else {
        Object.getPrototypeOf = function (object) {
            // May break if the constructor has been tampered with
            return object.constructor.prototype;
        };
    }
}

100% 正解というわけではありませんが (.constructor プロパティは任意のオブジェクトで変更可能であるため、ある時点でユーザーによって操作される可能性が十分にあるため)、上記のコードは、ブラウザーが ECMAScript 3.1 と良好な互換性を持つようになるまで、あなたを追い越してください。

そして、これが私が思いついたものです

if (typeof Object.getPrototypeOf !== "function") {
    if (Object.prototype.__proto__ === null) {
        Object.getPrototypeOf = function getPrototypeOf(object) {
            return object[proto];
        };
    } else {
        Object.getPrototypeOf = function getPrototypeOf(object) {
            if (object === Object.prototype) {
                return null;
            }

            if (object === object.constructor.prototype) {
                return Object.prototype;
            }

            return object.constructor.prototype;
        };
    }
}

コメントで述べたように、これにより、John Resig バージョンで経験した循環プロトタイプ チェーンの問題が解決されます。

私が抱えている問題(コンストラクターが改ざんされた場合に壊れる可能性があることを除く)は、テスト中に特定のテストで誤った結果が得られることがわかったことです(他にもあるかもしれませんが、まだそうではありません見つかった)。テストはエラーオブジェクトに関係します

インスタンス

new TypeError() instanceof Error; // --> true

ES5 Object.getPrototypeOf または _ proto _を使用した関数 instanceOf

instanceOf(new TypeError(), Error); // --> true

object.constructor.prototype フォールスルーを持つ関数 instanceOf

instanceOf(new TypeError(), Error); // --> false

他のすべてのテストでは一致する結果が得られましたが、前述したように、(コンストラクターが改ざんされていない) もっと多くの不整合がある可能性があります。これは私が思いついた最高のものですが、少なくとも私の質問で与えられたものと同様の関数で無限ループが発生する可能性はもうありません.

これは、問題を示すjsfiddleです。(Chromium v​​25、FireFox v20、および Opera 12.14 でテスト済み: 私が利用できるのはこれらだけです)

于 2013-05-31T07:20:03.787 に答える