真的没有办法在 IE (<8) 中暴露 html 元素的原型吗?

IT技术 javascript internet-explorer dom prototype-programming
2021-03-12 08:23:33

我编写了一个模式来使用它们的原型创建和扩展 html 元素。这在非 ie 浏览器中就像一个魅力。示例代码可以在@jsbin找到(见页面源码)

这种模式的优势应该是速度(方法在元素原型链中,所以它们被引用一次)。你猜对了:IE 不行。在 IE < 8 中,html 元素的原型是隐藏的/不可访问的,因此对于您创建的每个元素,您必须再次引用非标准方法(如果您大量使用该模式,则会留下很多指针)。我在网上搜索了解决方案,但只找到了复杂的解决方法。有没有真的没有办法访问HTML元素的原型在IE浏览器?

3个回答

不,也不能保证您可以在 JavaScript 中处理 DOM 对象的原型。DOM 对象不是 ECMAScript 规范的一部分;在任何浏览器中,它们可能根本不是(而且传统上讲不是)原生 JavaScript 对象。

这就是框架倾向于拥有自己的“容器”包装类的原因。

此外,即使它们是本机 JS 对象,您也不能依赖 't.el.constructor'。'constructor' 不是标准属性,在 IE 中不可用,甚至在 Mozilla 中也不会执行您可能认为的操作。避免。

此外,构造函数属性为 ECMAScript 3 中的原生对象指定的;只需ecma-international.org/publications/files/ECMA-ST-ARCH /... 中.constructorconstructor propertyCTRL-F 它们仍然在 ECMAScript 5中指定。不过,似乎没有一般规则,即构造函数的属性必须有一个指向构造函数的属性,所以我认为宿主对象可以有一个愚蠢的属性,而不会在技术上违反规范,但是在练习他们没有。prototypeconstructorconstructor
2021-04-22 08:23:33
此外,在最新版本的DOM Living Standard 中,所有 DOM 对象都保证行为合理,因为它们是使用WebIDL声明的,其中规定接口对象必须作为全局对象的属性存在,除非NoInterfaceObject指定,并且原型对象必须具有constructor指向接口对象的属性。因此,在 2009 年仍然存在一些规范的歧义,现在已经整理好了。
2021-05-07 08:23:33
其中大部分内容已过时,即使发布时我也不确定它是否全部正确。在指定接口时,旧的DOM Level 3和当前的DOM Living Standard都明确引用了构造函数ECMAScript 3(参见第 4.2.1 节)和ECMAScript 5规范规定构造函数具有prototype属性。
2021-05-09 08:23:33
当然,IE 7 不符合规范,所以这个答案在 2009实际上是正确的。我只是不确定它是否严格正确,假设我们打算将“保证”和“标准”解释为“保证”按规格'。综上所述,感谢您(六年前)发表的言论促使我(今天)深入了解所有这些事情的具体地点和方式。我花了几个小时来掌握所有这些东西,并通过我所有的新规范知识感到律师和授权。
2021-05-17 08:23:33

是的,真的没有办法做到这一点。

IE 元素是基于 COM 对象的,它们实际上不允许将任意成员添加到它们的接口中(在 COM 中,接口是一种契约,永远不应该改变)。这些接口的实现不能被 Javascript 扩展,元素根本就不是原型。

IE 添加了一个特殊的接口,旨在与 Javascript 一起使用,以允许向特定实例添加新成员,但您不能向“类”添加新成员,因为没有原型可以摆弄。

以下内容是从文章HTMLElement 中剪切和粘贴的,不适用于 IE示例在 IE 和 Firefox 中完美运行。

<html>
<head>
    <script type="text/javascript" src="DOMElement.js"></script>
    <script type="text/javascript">

        var DOMElement =
        {
            extend: function(name,fn)
            {
                if(!document.all)
                    eval("HTMLElement.prototype." + name + " = fn");
                else
                {
                    //
                    //  IE doesn't allow access to HTMLElement
                    //  so we need to override
                    //  *document.createElement
                    //  *document.getElementById
                    //  *document.getElementsByTagName
                    //

                    //take a copy of
                    //document.createElement
                    var _createElement = document.createElement;

                    //override document.createElement
                    document.createElement = function(tag)
                    {
                        var _elem = _createElement(tag);
                        eval("_elem." + name + " = fn");
                        return _elem;
                    }

                    //take copy of
                    //document.getElementById
                    var _getElementById = document.getElementById;

                    //override document.getElementById
                    document.getElementById = function(id)
                    {
                        var _elem = _getElementById(id);
                        eval("_elem." + name + " = fn");
                        return _elem;
                    }

                    //take copy of
                    //document.getElementsByTagName
                    var _getElementsByTagName = document.getElementsByTagName;

                    //override document.getElementsByTagName
                    document.getElementsByTagName = function(tag)
                    {
                        var _arr = _getElementsByTagName(tag);
                        for(var _elem=0;_elem<_arr.length;_elem++)
                            eval("_arr[_elem]." + name + " = fn");
                        return _arr;
                    }
                }
            }
        };

        DOMElement.extend("foo",function(){alert('bar')});
        DOMElement.extend("about","DOMElement v0.1")
        DOMElement.extend("contents",function(){return this.innerHTML})
        var elem = document.createElement("div");
        elem.foo();

        onload = function()
        {
            var elem2 = document.getElementById("myDiv");
            alert(elem2.about);

            var divs = document.getElementsByTagName("div");
            for(var i=0;i<divs.length;i++)
                alert(divs[i].contents())
        }

    </script>
</head>
<body>

    <div id="myDiv">hi</div>
    <div id="div2">there</div>

</body>
</html>

试试看

不要用魔鬼eval!!!!例如,而不是eval("_elem." + name + " = fn");使用_elem[name] = fn;
2021-04-23 08:23:33