0

我一直在浏览一些 shim/polyfill 库,发现其中一些有Object.getPrototypeOf. 在不存在时,它们会使用__proto__,如果不存在,则使用object.constructor.prototype.

我知道这__proto__是“非标准的”,虽然与Object.getPrototypeOf方法略有不同,但它们可以互换。

我也明白,原则上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 的博客,我重新设计了通用 shim,因为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 回答