我正在尝试确定某个对象是否可以进行字符串化。此检查适用于Chrome和Safari,但不适用于FF(25.0.1)。
var good = true;
var myObj = {"param1":11, "param2": "a string", "param3": $("a")};
//some cyclic object, specifically I have a jQuery object I got via `$("a")`
//which returned several anchor tags.
//try to stringify, which supposedly rejects cyclic objects
try {
JSON.stringify(myObj);
} catch(error){
good = false;
}
console.log(good) //returns true.
没有抛出错误......或者我没有正确捕捉它?我从来没有打过电话使用过try ... catch,所以我对它的细微差别的经验是空的。
JSON.stringify(myObj)
返回对象的字符串版本,没有很多对象参数,显然无法进行字符串化。根据{{3}},它应该是错误的。
谢谢!
答案 0 :(得分:4)
你正确地捕捉到了这个错误,但是(正如你已经确定的那样)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
仅捕获对象自己的属性,而不是原型属性。
在Firefox中,DOM对象大多没有自己的属性;相反,属性访问被委托给原型链到HTMLElement.prototype
,Element.prototype
或Node.prototype
(或元素的直接原型,如HTMLDivElement.prototype
或HTMLAnchorElement.prototype
)
您可能想知道:如果访问DOM元素上的属性会导致原型访问,那么DOM元素如何具有不同的属性值?并非所有DOM元素都具有或多或少相同的原型链吗?
这里的技巧是原型属性没有值,它们是 getter 函数。例如,当您要求firstChild
的{{1}}时,JavaScript引擎会执行以下步骤:
HTMLDivElement
属性。它不存在。firstChild
属性。firstChild
上找到firstChild
。Node.prototype
由访问者属性描述符定义,这意味着属性访问会导致执行Node.prototype.firstChild
函数。get
值是特定的DOM元素,您要求的this
值/ Firefox使用firstChild
值来做一些引擎盖下的内容查找DOM元素的第一个孩子。因此,当你这样做时:
this
你真的在做:
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`