“递归太多”使用instanceof而不是typeof时出错?
我正在制作一个函数将对象中的所有日期转换为字符串,当我使用以下函数时,我在 FF 中收到错误“太多递归”。 (它在 IE 和 chrome 中也失败)
function datesToString(obj) {
if (obj instanceof Object) {
if (obj instanceof Date) {
obj = "this part does not matter";
} else {
for (var key in obj) { obj[key] = datesToString(obj[key]); }
}
}
return obj;
}
但是当我将其更改为使用 typeof 时它工作正常吗?
function datesToString(obj) {
if (obj && typeof obj == "object") {
if (obj instanceof Date) {
obj = "this part does not matter";
} else {
for (var key in obj) { obj[key] = datesToString(obj[key]); }
}
}
return obj;
}
应该是相同数量的递归。我错过了什么吗?为什么我在第一个示例中遇到错误,但在第二个示例中却没有?
更新: 这是我正在使用的对象的示例(以 json 形式),
Contact = {
"LContactID": "00000000-0000-0000-0000-000000000000",
"CellPhone": "",
"HomePhone": "4564564560",
"OtherPhone": "",
"BirthDate": new Date(-62135575200000),
"SSN": "456456456",
"HowToContact": 1,
"ContactType": 3,
"Address1": "123 test",
"Address2": "apt. 1",
"City": "Valparaiso",
"State": "IN",
"Zip": "46383",
"FullAddress": "123 test, apt. 1",
"BuilderID": "",
"FullAddressWithCityState": "123 test\r\napt. 1\r\nValparaiso, IN 46383",
"WorkHours": "9-5",
"ContactTime": "",
"ContactMethod": "???",
"IsMilitaryOrSelfEmployed": false,
"AlternateContactName": "",
"AlternateContactPhone": "",
"ContactID": "00000000-0000-0000-0000-000000000000",
"Password": null,
"FirstName": "updatetest",
"MiddleName": null,
"LastName": "test_",
"Suffix": null,
"EmailAddress": null,
"EmailAddressAlternate": null,
"WorkPhone": "6546546540",
"WorkPhoneExt": null,
"CreatedOn": new Date(1263597309000),
"CreatedOnOverride": new Date(-62135575200000),
"ModifiedOn": new Date(1264014749000),
"SCRep": "",
"HBCRep": "",
"PPPRep": "",
"DPSRep": "",
"DRSRep": "",
"RDRep": "",
"OwnerID": "00000000-0000-0000-0000-000000000000",
"FullName": "updatetest test_",
"ImportID": 0,
"IncludeEmail": false,
"PreferredLanguage": 1,
"CarbonCopyList": [],
"HearAboutUs": 5,
"HearAboutUsOther": "",
"init": function() { },
"update": function() { },
"load": function() { }
}
看起来当我删除方法参数(init、update 和 load)时,它可以与 instanceof 示例一起使用。
更新:事实证明,这是一个 ASP.Net ScriptManager 问题。抱歉,没有包括我正在使用 ASP.Net 网站的事实。ASP.Net ScriptManager 将 Function 方法原型化,这会在函数上执行递归 for in 循环时导致无限循环。
I was making a function to convert all dates in an object to strings and when I used the following function I got a error in FF "too much recursion". (It also fails in IE and chrome)
function datesToString(obj) {
if (obj instanceof Object) {
if (obj instanceof Date) {
obj = "this part does not matter";
} else {
for (var key in obj) { obj[key] = datesToString(obj[key]); }
}
}
return obj;
}
but when I changed it to use typeof it worked fine?
function datesToString(obj) {
if (obj && typeof obj == "object") {
if (obj instanceof Date) {
obj = "this part does not matter";
} else {
for (var key in obj) { obj[key] = datesToString(obj[key]); }
}
}
return obj;
}
It should be the same amount of recursion. Am I missing something? Why am I getting an error with the first example but not the second?
Update:
here is an example of the object I was using (in json form)
Contact = {
"LContactID": "00000000-0000-0000-0000-000000000000",
"CellPhone": "",
"HomePhone": "4564564560",
"OtherPhone": "",
"BirthDate": new Date(-62135575200000),
"SSN": "456456456",
"HowToContact": 1,
"ContactType": 3,
"Address1": "123 test",
"Address2": "apt. 1",
"City": "Valparaiso",
"State": "IN",
"Zip": "46383",
"FullAddress": "123 test, apt. 1",
"BuilderID": "",
"FullAddressWithCityState": "123 test\r\napt. 1\r\nValparaiso, IN 46383",
"WorkHours": "9-5",
"ContactTime": "",
"ContactMethod": "???",
"IsMilitaryOrSelfEmployed": false,
"AlternateContactName": "",
"AlternateContactPhone": "",
"ContactID": "00000000-0000-0000-0000-000000000000",
"Password": null,
"FirstName": "updatetest",
"MiddleName": null,
"LastName": "test_",
"Suffix": null,
"EmailAddress": null,
"EmailAddressAlternate": null,
"WorkPhone": "6546546540",
"WorkPhoneExt": null,
"CreatedOn": new Date(1263597309000),
"CreatedOnOverride": new Date(-62135575200000),
"ModifiedOn": new Date(1264014749000),
"SCRep": "",
"HBCRep": "",
"PPPRep": "",
"DPSRep": "",
"DRSRep": "",
"RDRep": "",
"OwnerID": "00000000-0000-0000-0000-000000000000",
"FullName": "updatetest test_",
"ImportID": 0,
"IncludeEmail": false,
"PreferredLanguage": 1,
"CarbonCopyList": [],
"HearAboutUs": 5,
"HearAboutUsOther": "",
"init": function() { },
"update": function() { },
"load": function() { }
}
It looks like when I remove the method parameters (init,update and load) it works with the instanceof example.
UPDATE: This is a ASP.Net ScriptManager problem it turns out. Sorry for not including the fact that I was working with an ASP.Net website.The ASP.Net ScriptManager prototypes methods to Function which causes an infinity loop when doing a recursive for in loop on a function.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
(首先,让我说我在 FF 3.5.7 上尝试了你的代码,它没有遇到无限递归。也许你使用了不同的输入示例?)
无论如何,回答你的问题:
(a)为什么你会得到无限递归?因为一个对象可能会引用它自己。如果
of==o
那么在o
上调用你的函数将会触发对of
的后续调用,这实际上是o
等等...(b) 为什么两个版本有差异?
obj instanceof Object
检查 obj 是否是Object
的实例或其子类的实例。鉴于每个 Javascript 对象都继承自 Object,那么这个条件就很简单了,因此毫无意义。最终结果是第一个if
总是成功。另一方面,typeof obj == "object"
检查 obj 是否是 Object 的实例。例如,如果obj
是 String 的实例(在这种情况下typeof obj
产生String
),这可能是错误的。因此,存在差异。(First, let me say that I tried your code on FF 3.5.7 and it didn't run into an infinite recursion. maybe you used a different input example?)
Anyway, to answer your questions:
(a) Why do you get an infinite recursion? Because an object may refer to itself. If
o.f==o
then calling your function ono
will fire a subsequent call ono.f
which is actuallyo
and so on...(b) Why the difference between the two versions?
obj instanceof Object
checks if obj is an instance ofObject
or an instance of a subclass thereof. Given that every Javascript object inherits from Object then this condition is trivially true, and is thus meaningless. Net result is that the firstif
always succeeds. On the other handtypeof obj == "object"
checks that obj is an instance of Object. This may be false, for example, ifobj
is an instance of String (at which casetypeof obj
yieldsString
). Hence, the difference.