为什么有时我的JavaScript函数"未定义"?
我调用我的JavaScript函数。为什么有时在定义时会出现错误" myFunction未定义"?
例如。即使在此示例中,我有时也会得到"未定义copyArray":
function copyArray( pa ) { var la = []; for (var i=0; i < pa.length; i++) la.push( pa[i] ); return la; } Function.prototype.bind = function( po ) { var __method = this; var __args = []; // Sometimes errors -- in practice I inline the function as a workaround. __args = copyArray( arguments ); return function() { /* bind logic omitted for brevity */ } }
如我们所见,copyArray是在此处定义的,因此这与脚本文件的加载顺序无关。
我一直在难以解决的情况下遇到这种情况,其中调用函数位于另一个文件中,该文件应在被调用函数之后加载。但这是我能提出的最简单的情况,并且似乎是同样的问题。
它不会100%地发生,因此我确实怀疑某种与负载计时有关的问题。但是我不知道该怎么办。
@Hojou:那是问题的一部分。我现在遇到此错误的函数本身就是我的addLoadEvent,它基本上是公共库函数的标准版本。
@James:我理解这一点,并且该函数中没有语法错误。在这种情况下,也会报告语法错误。在这种情况下,我只会收到"未定义"错误。
@David:在这种情况下,脚本位于一个外部文件中,该文件使用页面头部的常规<script src =" file.js"> </ script>方法进行引用。
@Douglas:有趣的想法,但是如果是这种情况,我们怎么能自信地调用用户定义的函数?无论如何,我都尝试过,但没有成功。
@sk:此技术已在各种浏览器上进行了测试,并且基本上是从Prototype库中复制的。
解决方案
我的猜测是,在调用该方法时,某种程度上文档还没有完全加载。在文档准备就绪事件之后让代码执行。
函数或者其上方代码中的语法错误可能导致其未定义。
如果仅在页面上包含脚本,则不可能发生这种情况。
无论JavaScript代码是在JavaScript代码之前还是之后进行声明," copyArray"函数始终应该可用,除非我们使用依赖库动态加载JavaScript文件。如果是这样的话,时间安排会出现各种各样的问题。
使用匿名函数来保护本地符号表。就像是:
(function() { function copyArray(pa) { // Details } Function.prototype.bind = function ( po ) { __args = copyArray( arguments ); } })();
这将创建一个在本地符号表中包含函数的闭包,并且在调用函数时不必依赖于全局命名空间中可用的闭包。
如果要更改内置"功能"对象的原型,则可能通过修改基本内置对象而遇到浏览器错误或者竞争状态。
在多个浏览器中对其进行测试以找出答案。
恐怕,当我们将新方法添加到Function类(通过原型设计)时,实际上是将其添加到所有声明的函数中,以及添加到copyArray()中。结果,copyArray()函数被递归地自我引用。 IE。应该存在copyArray()。bind()方法,该方法正在调用自身。
在这种情况下,某些浏览器可能会阻止我们创建此类参考循环并引发"函数未定义"错误。
在这种情况下,内联代码将是更好的解决方案。
这不能解决原始问题,但是我们始终可以将对copyArray()的调用替换为:
__args = Array.prototype.slice.call(arguments);
可从Google获得更多信息。
我已经在以下浏览器中测试了以上内容:IE6、7和8B2,Firefox 2.0.0.17和3.0.3,Opera 9.52,适用于Windows 3.1.2的Safari和Google Chrome(无论本文发布时的最新版本) ),并且可以在所有浏览器中使用。
使用JSLint验证代码。通常会发现大量的小错误,因此警告" JSLint可能会伤害感觉"很明显。 =)
尽管Chromium可以很好地处理此功能,但我无法将其识别为最新版Firefox for Linux中的定义。
在我的情况下发生的事情是,在定义有问题的功能的代码块之前,我有一个以前的" SCRIPT"代码块,它用以下方式表示:
<SCRIPT src="mycode.js"/>
(也就是说,没有结束标记。)
我必须以以下方式重新声明此块。
<SCRIPT src="mycode.js"></SCRIPT>
然后接下来发生的事情很好...奇怪吗?