今天,同学在编写javascript说碰到一个奇怪的问题,函数调用的时候无法正确传值,过去看了一下,代码是:
<script language="javascript" type="text/javascript">
function output () {
document.write("abc');' />");
}
function f(id)
{
alert(id);
}
< SPAN>script>
当然,代码远比这个复杂的多,这里把它给简化了,原理是一样的,都是想把字符串“abc”传递给f(id)。
粗看一下代码并没有语法错误,但是直接运行会出错,特意把outPut里的函数调用onClick='f('abc');'修改为onClick='f(abc);',运行成功,所显示的值是空值,最有意思的是将其修改为onClick='f(123);'这种纯数字的值却可以得到正确结果。
于是坐下来静心研究了一下,终于找到了原因。众所周知,程序的括符和引号的配对问题,编译平台利用的是以堆栈来处理,由于括符有左扩符“{”、“(”和右扩符“)”、“}”之分,所以在进栈和出栈的处理上基本上不会出现配对错误的情况,可以精确的将程序按作者的想法分为对应的代码块。正因为这样,很多人都会惯性的以为引号也是像括符配对一样从最外层开始以一层嵌套一层地往内检查编译,上面的代码犯的其中一个就是这种错误。
由于引号只有“’”和“””这两种,开始和结束符号都是相同的,因此平台自然就无法像括符的处理那么精确,例如有一个字符串:’ab’cd’ef’,对编译器来说,只有ab和ef是包含在引号里面而已,有点类似英语语法中的“就近原则”。同时也因为这种“原则”,所以引号理论上只能嵌套两层,给引号的多层嵌套带来了非常大的因难,上面代码犯的第二个错误就是这种。
好了,明白了一点原理性的东西,那么上面代码的改错还不是手到擒来了。代码的原意是想传递一个字符串,但是想当然的硬搞了个三层嵌套,所以事件处理函数'f('abc');'将被看成是'f(' abc ‘);’三个独立个体,基本语法出错。将’abc’两边的引号去掉,语法成功能过,不过弹出的是一个空值,而将“abc”替换成“123”这类纯数字的值则能够得到正确的结果,这又是什么原因呢?
这时大家想到什么没有?没错,其实只要把最外层的双引号去掉就一目了然了。当你输入“123”这类纯数字的时候,程序将以整型变量值传递给函数f(id),然后再经过平台自已转换成字符串类型显示出来。但是对于“abc”这类看似字符串的序列,编译平台无法判定“abc”到底是什么,函数?字符串?都不是,那最终只能判定它为变量,既然是变量,程序并没有为其赋值,那么传递过去的也就只能是空值了。这样,关于上面所说的一切奇怪的现在都有了个完整的解释了。接下来就动手修改代码了,既然编译平台将“abc”当成一个变量,那么咱就如期所愿,将它定义为一个变量并为其赋值,轻松解决。
<script language="javascript" type="text/javascript">
function output () {
var values = "abc";
document.write("");
}
function f(id)
{
alert(id);
}
< SPAN>script>
虽然这只是一个很小很小的问题,但由于这种想当然的惯性思维引发的错误却是可大可小,写下这篇文章,在这里给自己留个脚印,引以为戒。
