JSON.parse不会在循环对象上出错 [英] JSON.parse not erroring on cyclic objects
问题描述
var good = true;
var myObj = {param1:11,param2:a string,param3:$(a)};
//一些循环对象,特别是我有一个jQuery对象,我通过`$(a)`
// //返回了几个锚标签。
//尝试字符串化,据推测会拒绝循环对象
try {
JSON.stringify(myObj);
} catch(error){
good = false;
}
console.log(good)//返回true。
没有错误发生,或者我没有正确地捕捉到它?我以前从来没有打过电话来尝试使用try ... catch,所以我对它的细微差别的经验是空的。
JSON.stringify myObj)
返回一个字符串版本的对象,sans许多对象参数显然不能字符串化。它应该根据 MDN ,错误。
谢谢!
您正确地捕捉错误,但是(如您所识别的) 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
只会捕获一个对象自己的属性,而不是原型属性。
$ b 奖金信息:超过你想要的了解DOM
在Firefox中,DOM对象大多没有自己的属性;相反,属性访问是通过原型链委托给 HTMLElement.prototype
, Element.prototype
或 Node.prototype
(或元素的直接原型,如 HTMLDivElement.prototype
或 HTMLAnchorElement.prototype $您可能想知道:如果访问DOM元素上的属性会导致原型访问,DOM元素如何具有不同的属性值?不是所有的DOM元素都有相同的原型链吗?
这里的技巧是原型属性没有值,它们是 getter 函数。例如,当您询问 HTMLDivElement
的 firstChild
时,JavaScript引擎会执行以下步骤:
- 查找对象本身的
firstChild
属性。它不在那里。
- 在对象原型上查找
firstChild
属性。
- 继续直到我们在
Node.prototype
上找到 firstChild
。
-
Node.prototype.firstChild
是由访问器属性描述符定义的,这意味着属性访问导致执行 get
- 执行getter函数时,
this
值是特定的DOM元素,其 firstChild
您要求的值/ Firefox使用这个
值来进行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); //将`this`设置为`elm`来调用getter
或者(更少可读):
var val = Object.getOwnPropertyDescriptor(document.getElementById(header).__ proto __.__ proto __.__ proto __.__ proto__,firstChild ).get.call(document.getElementById(header))
I'm trying to determine if an object can be stringified or not. This check works in Chrome and Safari, but not in 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.
No error thrown... or I'm not catching it properly? I've never had call to use try... catch before now, so my experience with its nuances is null.
JSON.stringify(myObj)
returns a string version of the object, sans many of the object parameters which obviously can't be stringified. It should, according to MDN, error.
Thanks!
解决方案 You're catching the error properly, but (as you've identified) Firefox simply isn't throwing an error.
This is because Fiefox doesn't choke on JSONification of DOM objects, where other browsers do:
JSON.stringify(document.getElementById("header"))
In Chrome and Safari, this line results in an error (because in WebKit/Blink, cyclic DOM objects like siblings exist directly on each DOM object), while in Firefox with harmlessly produces the string "{}
".
This is because Firefox's DOM objects do not have any of their own enumerable properties:
Object.keys(document.getElementById("header"))
> []
In WebKit/Blink browsers, this line provides an array of property names as strings, because DOM object have their own properties. JSON.stringify
only captures an object's own properties, rather than prototype properties.
Bonus Info: More Than You Wanted to Know About the DOM
In Firefox, DOM objects mostly don't have their own properties; instead, property access is delegated up the prototype chain to the HTMLElement.prototype
, Element.prototype
, or Node.prototype
(or the element's immediate prototype, like HTMLDivElement.prototype
or HTMLAnchorElement.prototype
).
You might wonder: if accessing a property on a DOM element results in prototype access, how can DOM elements have different property values? Don't all DOM elements have more or less the same prototype chain?
The trick here is that the prototype properties don't have values, they are getter functions. For example, when you ask for firstChild
of a HTMLDivElement
, the JavaScript engine takes the following steps:
- Look for the
firstChild
property on the object itself. It's not there.
- Look for the
firstChild
property on the object's prototype.
- Continue up the prototype chain until we find
firstChild
on Node.prototype
.
Node.prototype.firstChild
is defined by an accessor property descriptor, meaning that property access results in the execution of a get
function.
- The
this
value during the execution of the getter function is the particular DOM element whose firstChild
value you asked for/ Firefox uses that this
value to do some under-the-hood lookup of the DOM element's first child.
Thus, when you do:
var val = document.getElementById("header").firstChild;
you're really doing:
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`
Or (less readably):
var val = Object.getOwnPropertyDescriptor(document.getElementById("header").__proto__.__proto__.__proto__.__proto__, "firstChild").get.call(document.getElementById("header"))
这篇关于JSON.parse不会在循环对象上出错的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!