【问题标题】:HTMLElement.toString() only works in ChromeHTMLElement.toString() 仅适用于 Chrome
【发布时间】:2012-01-02 16:41:23
【问题描述】:

我在 FireFox 和 Opera 中发现了一个错误。(我正在运行 Debian Whezee、Firefox 9.0.1、Opera 11.60、Chrome 16.0.912.63) 当您键入这样的内容时:

var a = document.createElement('a')
a.toString = function(){ return "Hello" }
alert(a+" World");

在 Chrome 中,您会看到带有“Hello World”的警告框,但在 firefox 和 opera(不了解 IE)中,您会看到类似“[object HTMLElement] World”的内容

我试图解决这个问题:

Object.prototype.toString = function(){ return "Hello" };
Function.prototype.toString = function(){ return "Hello" };

它不起作用因为 DOM 元素不是 Object(不继承自 Object 并因此继承 Function),甚至这也没有帮助:

HTMLElement.prototype.toString = function(){ return "Hello" };
Element.prototype.toString = function(){ return "Hello" };
Node.prototype.toString = function(){ return "Hello" };

因为 HTMLElement、Element、Node 都是接口而不是函数。

现在我的问题是在哪里报告这个错误?有人可以帮我解决这个问题吗?

//编辑

这是我原来的 toString 函数:

var a = document.createElement('a');
a.toString = function(){
    var tmp=document.createElement('div');
    tmp.appendChild(this);
    return tmp.innerHTML;
}

如您所见,这是 outerHTML 的替代方法,我需要将其作为下一行中的默认行为

document.getElemntById('someID').innerHTML += "click this link:"+a;

结果应该是这样的:

<div id='someID'>click this link:<a></a></div>

【问题讨论】:

  • 谁说这是一个错误?显然,Firefox 和 Opera 不允许覆盖 DOM 节点的 toString。因为它们是宿主对象,它们不受 ECMAScript 规范的约束,所以完全没问题。
  • 所以也许有人知道我能做些什么来获得类似的效果。是否有任何其他方法可以覆盖可以解决问题。因为当我使用 Chrome 而其他人使用 Firefox 或 Opera 时,每次使用 a.toString() 并不是那么明显。我通常会说“奇怪,我的工作正常”,然后在需要的地方默默地添加 .toString()。
  • 问题是,您究竟希望您的toString 函数做什么?如果你真的只想获取内部文本,你应该使用innerTexttextContent。这是标准方式。
  • @fon60 为什么不只是alert( a.innerHTML + ' World' );
  • 我记得我自己一件事。此方法在对象中定义,但默认情况下引擎/javascript 不调用此方法。所以当我做 alert(a.toString()+" World");到处都能正常工作。我感兴趣的是。数组对象有 toString 可以被覆盖,但为什么 DOM 元素没有这个。请让 Node 继承自 Object。请。

标签: javascript firefox dom tostring


【解决方案1】:

我认为没有任何地方可以报告这一点,因为在 dom 元素上调用 toString 不是标准行为。要从您应该使用 innerHTML 的元素中获取 html 内容,并仅获取文本内容,textContent(或旧版 IE 浏览器的 innerText)

【讨论】:

  • 我的 .toString 函数更像:
  • 对不起,我已经开始回答了,但决定编辑原始问题并忘记删除此评论。
【解决方案2】:

每当您尝试更改项目的默认/本机行为时;这几乎总是一个的想法。我想我可能会建议:

var aa = document.createElement('a');
document.body.appendChild(aa);
var nodeList = document.getElementsByClassName('*');
for (var i = 0, len = nodeList.length; i < len; i ++) {
    nodeList[i].myCustomFunction = toStringOverride;
}
function toStringOverride() {
    return "Hello ";
}

alert(aa.myCustomFunction() + " World");

【讨论】:

  • 一个可能有用的情况是,如果你有一堆函数期望某个参数是一个字符串,但是你有一个新的要求,它们也可以是一个 HTML UI 元素(在在这种情况下你想使用元素的值)。现在您必须为每个函数显式添加检查/转换,而如果它们已经转换为字符串,则只需在要传递的每个元素中覆盖 toString
【解决方案3】:

数组对象有toString可以覆盖,但是为什么DOM元素没有这个

Array 是原生 JavaScript 对象。 ECMAScript 标准规定了 JS 对象如何工作的要求,包括将不同的toString 破解到原型中的能力。

然而,DOM 对象并未在任何地方指定为原生 JS 对象或遵守 JS 对象的一般行为规则。它们被允许成为标准所称的“宿主对象”,但没有那么明确。

破解他们的原型是非常不可靠的,根本不是一个好主意。一个JS库prototype.js,试过了,结果是messy

请让 Node 继承自 Object。请

抱歉,Stack Overflow 无权要求 Node 是原生 JavaScript 对象!

在您说服所有浏览器供应商对 DOM 的原生 JS 对象进行标准化之前,您必须使用外部 function Node_getOuterHTML(node) { ... } 并明确调用它,"click this link:"+Node_getOuterHTML(a)

虽然,通常最好将您创建的节点直接附加到文档中,而不是通过 DOM->HTML-markup->DOM 序列化和解析周期发送它,它目前正在经历innerHTML .

【讨论】:

  • 你对 DOM 的“原生”(或更准确地说是“非代理”)JS 对象进行标准化的机会恰好是 0,因为 Web 兼容需要来自 DOM 的行为,而原生对象根本无法做到有每个规格。 DOM 中的很多东西都可以是原生对象,但还有很多东西不能。
猜你喜欢
  • 2021-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-20
  • 2017-09-16
  • 2015-05-19
  • 2019-03-29
  • 1970-01-01
相关资源
最近更新 更多