您正在正确地捕获错误,但是(正如您所确定的)Firefox根本不会引发错误。
这是因为Fiefox不会阻塞DOM对象的JSON化,而其他浏览器却会这样做:
JSON.stringify(document.getElementById("header"))在Chrome和Safari中,此行会导致错误(因为在WebKit /
Blink中,循环DOM对象(例如同级兄弟)直接存在于每个DOM对象上),而在Firefox中则无害地生成了字符串“
{}”。这是因为Firefox的DOM对象没有任何自己的可枚举属性:
Object.keys(document.getElementById("header"))> []在WebKit /
Blink浏览器中,此行以字符串形式提供属性名称数组,因为DOM对象具有自己的属性。
JSON.stringify仅捕获对象自身的属性,而不捕获原型属性。
奖励信息:比您想了解的更多有关DOM
在Firefox中,DOM对象通常不具有自己的属性。相反,属性访问被委派了原型链的
HTMLElement.prototype,
Element.prototype或者
Node.prototype(或元素的直接原型,像
HTMLDivElement.prototype或
HTMLAnchorElement.prototype)。
您可能想知道: 如果访问DOM元素上的属性导致原型访问,那么DOM元素如何具有不同的属性值? 并非所有DOM元素都具有或多或少相同的原型链吗?
这里的技巧是原型属性没有 值 ,它们是 getter
函数。例如,当您要求输入
firstChild时
HTMLDivElement,Javascript引擎执行以下步骤:
firstChild
在对象本身上查找属性。不在那里firstChild
在对象的原型上查找属性。- 继续检查原型链,直到我们找到
firstChild
的Node.prototype
。 Node.prototype.firstChild
由 访问器属性描述符 定义,这意味着属性访问会导致get
函数的执行。this
在执行getter函数期间,该值是firstChild
您要求其值的特定DOM元素/ Firefox使用该this
值对DOM元素的第一个子元素进行了一些幕后查找。
因此,当您这样做时:
var val = document.getElementById("header").firstChild;您确实在做:
var elm = document.getElementById("header");var nodeProto = elm.__proto__.__proto__.__proto__.__proto__;var propDescriptor = Object.getOwnPropertyDescriptor(nodeProto, "firstChild");var getterFunc = propDescriptor.get;var val = getterFunc.call(elm); // invoke the getter with `this` set to `elm`或(不太可读):
var val = Object.getOwnPropertyDescriptor(document.getElementById("header").__proto__.__proto__.__proto__.__proto__, "firstChild").get.call(document.getElementById("header"))


