令人费解的 javascript 数组行为
Posted
技术标签:
【中文标题】令人费解的 javascript 数组行为【英文标题】:Puzzling javascript array behavior 【发布时间】:2010-11-15 11:03:47 【问题描述】:所以,这可能是一个非常愚蠢的问题,但我显然在这里遗漏了一些东西。
考虑以下代码:
var selectedItems = [];
selectedItems.push("0ce49e98-a8aa-46ad-bc25-3a49d475e9d3");
//fyi, selectedItems[selectedItems.length] = "0ce49e98-a8aa-46ad-bc25-3a49d475e9d3"; produced the same result.
最后selectedItems
的内容是这样的:
Name Value Type
------------- -------------------------------------- ------
selectedItems ... Object
- [0] "0ce49e98-a8aa-46ad-bc25-3a49d475e9d3" String
- length 1 Long
但如果我只是尝试在同一个字符串上调用 split(),如下所示:
selectedItems = "0ce49e98-a8aa-46ad-bc25-3a49d475e9d3".split(",")
现在我假设的数组的内容看起来像这样(缺少长度):
Name Value Type
------------- -------------------------------------- ------
selectedItems ... Object
- [0] "0ce49e98-a8aa-46ad-bc25-3a49d475e9d3" String
知道有什么区别吗?这里到底发生了什么? 提前致谢。
更新: 我感觉这两个结果值实际上在结构上有所不同,因为当我尝试将它传递给服务器端 WebMethod 时(没有实际的错误消息,但我知道通话失败)。我不确定。
更新 #2 我注意到以这种方式设置 targetLocationIdList 会导致“快速监视”窗口中不显示“长度”属性:
var params =
jobId : args.get_JobId(),
targetLocationIdList : retVal.split(',')
;
但此结果包含快速观察窗口中显示的“长度”属性:
var retValArr = [];
retValArr = retVal.split(',');
var params =
jobId : args.get_JobId(),
targetLocationIdList : retValArr
;
【问题讨论】:
"0ce49e98-a8aa-46ad-bc25-3a49d475e9d3".split(",").length === 1 您能否发布任何示例代码,表明这实际上是您的调试器以外的其他地方的问题? 【参考方案1】:以编程方式完全没有区别。如果您在 chrome 开发人员窗口和 firebug 中运行您的示例,它看起来像第二个
Name Value
Type
------------- -------------------------------------- ------
selectedItems ... Object
- [0] "0ce49e98-a8aa-46ad-bc25-3a49d475e9d3" String
长度是一个隐含的属性
编辑
var retVal = 'test';
var params =
jobId : 1,
targetLocationIdList : retVal.split(',')
;
console.log(params.targetLocationIdList.length) // prints 1
上面的代码在 IE8、Firefox、Chrome(在他们的开发工具或萤火虫中)打印 1,所以认为这一定是 Visual Studio 或 Atlas 显示对象的问题。
【讨论】:
查看 edeverett 回答下的评论。谢谢。 我在解释中添加了更多可能有用的内容【参考方案2】:这可能是调试器中的错误吗? (或者这会导致浏览器出现问题?)
【讨论】:
是的,当我尝试从对话框弹出窗口中返回此值时,这确实会给我在 IE7 中带来问题。 向我们展示不起作用的代码。我认为你一定做错了什么。在一种情况下,您可能正在查看字符串长度,而另一种情况是数组长度?无论如何,我们还没有足够的信息来提供帮助。【参考方案3】:在第一个实例中,您将 selectedItems 声明为一个数组,然后分配给它。
在第二种情况下,您直接从 split 方法分配给它。
我只能假设 VS 将数组声明作为显示长度属性的提示。
【讨论】:
【参考方案4】:您似乎在 Microsoft 的 javascript 实现中发现了一个缺陷。 Visual Studio 和 IE 可能共享相同的实现,这就是为什么您只在这两个程序中遇到错误,而不是在 Firefox 或 Chrome 中。
在 EMCAScript 标准中:http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf
15.5.4.14 String.prototype.split(分隔符、限制) 返回一个 Array 对象,其中存储了将此对象转换为字符串的结果的子字符串。
在Array Object的定义中:
15.4 数组对象 ... 每个 Array 对象都有一个长度属性,其值始终为非负整数 小于 232。
【讨论】:
【参考方案5】:您使用的是什么浏览器,您确定没有length
属性吗?我刚刚做了
var arr = "0ce49e98-a8aa-46ad-bc25-3a49d475e9d3".split(",")
在我的 Firebug 控制台中,arr
确实有一个等于 1 的 length
属性,正如预期的那样。
【讨论】:
我正在 Visual Studio 2008 中调试。是的,如果我在代码中实际调用 arr.length,则可用的 length 属性准确显示为 1。但是在 arr 上进行快速观看,在这种情况下不会显示“长度”。 听起来像是微软的缺陷 也许吧。但我感觉这两个结果值实际上在结构上有所不同,因为当我尝试将它传递给服务器端 WebMethod 时(没有实际的错误消息,但我知道调用失败)。 我只是在 Chrome 的控制台中查看了它,两个实体是相同的。我认为这是 Visual Studio 快速监视窗口。它可能认为一个是对象,另一个是数组(在 JavaScript 中数组和对象都报告为对象)。 我同意这是一个 Visual Studio 问题,如果它实际上在它之外运行良好。但是 IE7 中的 asp.net ajax (atlas) 代码错误。明天我会尽力提供更详细的信息。【参考方案6】:你怎么知道调用失败了?确保您在调试模式下运行,或使用失败的处理程序来通知原因。
【讨论】:
我知道它失败了,因为代码执行在 asp.net ajax 代码中中断。可悲的是,有一个 try and finally 块,但没有捕获。 :) 你的意思是有一个javascript错误——如果你让它运行,错误信息到底是什么?该 try/finally 块是处理来自服务器的响应的结果,因此您应该能够使用 Fiddler 来查看响应是什么,这也可能有一个重要的线索。 不,它不处理来自服务器的响应——请求永远不会到达服务器。 try/finally 块在 asp.net ajax 的前端脚本中。 没有错误信息,因为没有catch块——这就是问题所在。但我不打算去编辑和重建 asp.net ajax 程序集只是为了弄清楚这一点——不值得我花时间。我想也许有人已经遇到了类似的问题。 没有catch不代表没有错误。在 javascript 中,没有捕获的 try/finally 具有隐藏原始错误来源的不幸副作用。就像它重置了堆栈,所以错误似乎来自 finally 块而不是它真正来自哪里。如果您只是让错误发生,您应该会在浏览器的错误列表中看到一些内容。现在,这在 FF 中可能不是真的,因为它报告错误的方式存在错误,我已经报告过但已经引起了很多关注,所以试试 IE。 Mozilla 错误如果有兴趣:bugzilla.mozilla.org/show_bug.cgi?id=377347【参考方案7】:这是一个非常简单的测试:
var selectedItems = [];
selectedItems.push("0ce49e98-a8aa-46ad-bc25-3a49d475e9d3");
alert(selectedItems);
selectedItems = "0ce49e98-a8aa-46ad-bc25-3a49d475e9d3".split(",");
alert("boo");
alert(selectedItems.length);
boo 之后,我们检查是否还有长度。
回答:是的。 所以换句话说,这是 Visual Studio 的错误,仅此而已。
【讨论】:
你们没注意。请参考 Vinay Sajip 的回答下的 cmets。以上是关于令人费解的 javascript 数组行为的主要内容,如果未能解决你的问题,请参考以下文章
iPhone:iOS 6 和 5.1 之间 cellForRowAtIndexPath 行为的令人费解的差异
Flutter 令人费解的流行为:setState 调用但不重建 widget 树