在我正在开发的网站中,内容是用Ajax加载的,以及包含的任何JavaScript。我这样做是因为所有的页面都是相同的布局,但只有内容不同。
问题是,当"内容"中包含JavaScript时,我担心即使加载了新内容,脚本也会继续执行。所以我做了这个测试来确定。
首先是一个将加载2个其他页面的主页:
<script src="scripts/jquery.min.js"></script>
<script>
function loadPage1(){
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4 && xhttp.status == 200) {
response = xhttp.responseText;
$("#content").remove();
$("#mainContent").append(response);
}
};
xhttp.open("GET", "page1.html", true);
xhttp.send();
}
function loadPage2(){
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4 && xhttp.status == 200) {
response = xhttp.responseText;
$("#content").remove();
$("#mainContent").append(response);
}
};
xhttp.open("GET", "page2.html", true);
xhttp.send();
}
</script>
<button onclick="loadPage1()">Load page 1</button>
<button onclick="loadPage2()">Load page 2</button>
<div id="mainContent">
</div>
然后是两个包含JavaScript内容的页面,基本上只是每秒向控制台发送"我是x页面"。
第1页:
<div id="content">
<h1>Page 1</h1>
<script type="text/javascript">
setInterval(function(){
console.log("I am page 1");
},1000);
</script>
</div>
第2页:
<div id="content">
<h1>Page 2</h1>
<script type="text/javascript">
setInterval(function(){
console.log("I am page 2");
},1000);
</script>
</div>
Ajax加载良好,我可以看到h1
从Page 1
变为Page 2
。但在控制台中,我可以看到,即使内容被删除,第一个脚本仍然在垃圾邮件中。
有没有办法防止这种行为?最好将每个脚本放在适当的位置,而不是将所有脚本移动到"主页"。
EDIT:为了避免混淆,setInterval()
不是主要问题,它只是一个例子。我在问您通常如何处理Ajax和JavaScript 的此类问题
尽管第一个<script>
块已经被替换,但由于javascript的工作方式,您可以看到控制台日志。
您的匿名功能
function(){
console.log("I am page 1");
}
将继续执行,直到调用clearInterval
或离开此页面。
当您添加点击处理程序时也是如此,例如$('#some_button').on("click",function(evt){/*do something*/});
即使您声明了一个变量,如<script>var x='data1';</script>
然后删除封闭的<script>
标记,则变量x
将继续存在。
在这两种情况下,对函数和变量的引用都存储在某个地方。对setInterval和click处理程序函数的引用由事件处理程序持有。对您声明的任何var
和function
的引用都保存在window
对象中(除非您使用闭包)。
在新加载的脚本中,您可以重新分配内容:函数的行为将是最后加载的行为。对该函数的任何调用都将执行新指令,因为它们现在也已分配给窗口对象(作用域)。
总之,
- 您需要清除间隔
- 您声明的函数和变量将一直存在,直到您更改它们
回复:评论中的问题
哦,所以如果我为一个函数声明一个新的行为,它不会像静态编程语言那样给我一个错误。如果我能保持不变的话,这将为我节省很多工作。我想我所需要做的就是clearInterval,并保持任何函数的原样。
是的,但与其与其他编程语言进行比较,不如尝试将这些语言视为在将脚本标记注入DOM时立即解释的指令。因此,您所做的实际上只是重新分配窗口对象的属性。为了更好地理解这一点,请打开chrome上的开发人员控制台,并按以下顺序运行:
window.hasOwnProperty("xy")
var xy=1
window.hasOwnProperty("xy")
window.xy
xy="foo"
typeof window.xy
typeof window
这将帮助您了解JavaScript引擎是如何处理代码的。
您删除/替换了内容,而不是脚本,您仍然在同一页上。此外,您只将新数据加载到该页面中,因此您的脚本仍在该页面中运行,除非它明确停止或在页面重新加载时停止。