刚开始写AJAX代码的时候,直接参照的是AJAX基础教程一书中的代码(该书真的很不错,是AJAX入门的经典教材,是图灵出版社的。计算机方面的书籍,我最信任的就是O'R和图灵的)。
该书的创建XMLHttpRequest对象的代码如下:
03 |
function createXMLHttpRequest() |
05 |
if (window.ActiveXObject) |
07 |
xmlHttp = new ActiveXObject( "Microsoft.XMLHTTP" ); |
09 |
else if (window.XMLHttpRequest) |
11 |
xmlHttp = new XMLHttpRequest(); |
在一般情况下,该代码的使用不会带来任何问题。
如:
03 |
createXMLHttpRequest(); |
04 |
xmlHttp.onreadystatechange = handleStateChange1; |
05 |
url = "test.php?ts=" + new Date().getTime(); |
06 |
xmlHttp.open( "GET" , url, true ); |
12 |
createXMLHttpRequest(); |
13 |
xmlHttp.onreadystatechange = handleStateChange2; |
14 |
url = "test.php?ts=" + new Date().getTime(); |
15 |
xmlHttp.open( "GET" , url, true ); |
19 |
function handleStateChange1() { |
23 |
function handleStateChange2() { |
在页面的不同地方调用test1,test2函数都能正常工作。即不同时刻调用的话,就不会产生问题。
但是假如你需要在同一时刻同时调用这两个函数,则会发现只有其中一个可以正常运行。 比如,我在加载页面的时候运行如下函数:
此时,则test1,test2只有一个函数会正常执行。
分析下原因,是由于javascript的语言特性导致。一般情况下,Javascript的变量,函数等等,都是公用的,其他对象都能访问(可读可写)。这就是问题的所在。在同一时刻,调用test1和test2就会出现“变量xmlHttp”的冲突。
解决方法:
最简单的方法,不要在同一时刻调用,如init函数可以改为:
4 |
setTimeout( "test2()" ,500); |
但该方法属于投机,并未真正解决问题。
我们还可以修改“XMLHttpRequest创建函数”,改为一实例化函数。
01 |
function createXMLHttpRequest() |
03 |
if (window.ActiveXObject) |
05 |
var xmlHttpObj = new ActiveXObject( "Microsoft.XMLHTTP" ); |
07 |
else if (window.XMLHttpRequest) |
09 |
var xmlHttpObj = new XMLHttpRequest(); |
实例化时相应的改为:
03 |
xmlHttp_1 = createXMLHttpRequest(); |
04 |
xmlHttp_1.onreadystatechange = handleStateChange1; |
05 |
url_1 = "test.php?ts=" + new Date().getTime(); |
06 |
xmlHttp_1.open( "GET" , url, true ); |
12 |
xmlHttp_2 = createXMLHttpRequest(); |
13 |
xmlHttp_2.onreadystatechange = handleStateChange1; |
14 |
url_2 = "test.php?ts=" + new Date().getTime(); |
15 |
xmlHttp_2.open( "GET" , url, true ); |
这样子处理的话,即使在同一时刻调用test1,test2函数,也不会产生问题了,实现了真正的“同步”。
通过该方法,可以引申出javascript中对象的“私有属性”的创建方法:
- 私有属性可以在构造函数中使用 var 关键字定义。
- 私有属性只能由特权函数公用访问。(特权函数就是在构造函数中使用this关键字定义的函数)。外部客户可以访问特权函数,而且特权函数可以访问对象的私有属性。
比如下面这个Vehicle类,则wheelCount和curbWeightInPounds就是私有属性,只能通过特权函数访问/ 设置了:
04 |
var curbWeightInPounds = 4000; |
05 |
this .getWheelCount = function () |
09 |
this .setWheelCount = function (count) |
13 |
this .getCurbWeightInPounds = function () |
15 |
return curbWeightInPounds; |
17 |
this .setCurbWeightInPounds = function (weight) |
19 |
curbWeightInPounds = weight; |