原本在项目中的需求是这样的,向服务器提交一个Ajax请求后,在服务器的FTL中生成动态的数据后返回,同时在FTL模板文件中夹杂了一些JS脚本以及XX方法定义,渲染返回后直接作为文本添加到客户端页面DIV的innerHTML。先暂且不论这种方式的优劣,就这个需求看,大家应该理解我的用意是在页面中去调用Ajax返回生成的js代码。按我原来的想法,只要在回调函数返回后将我将要调用JS代码加载到当面页面中的某个DIV的innerHTML,包含XX方法,然后就可以顺利调用XX方法。但是事实上,会出现XX方法 is not defined的问题。我个人将这个问题定义为由于对浏览器对JS的渲染加载以及解释调用顺序不理解造成的设计错误。鉴于项目中的代码过于庞大,对于这个问题,我写了个测试页面来进行分析,新建一个test.htm:
<script>
function a(){
sadasd
alert("a");
}
function c(){
document.getElementById("test1").innerHTML="<script>function z(){alert(\"z\");}<\/script>";
z();
}
function d(){
document.getElementById("test2").innerHTML="";
b();
}
</script>
<input type="button" value="test_a" onclick="a();">
<input type="button" value="test_b" onclick="b();">
<input type="button" value="test_c" onclick="c();">
<input type="button" value="test_d" onclick="d();">
<div id="test1"></div>
<div id="test2">
<script>
function b(){
alert("b");
}
</script>
</div>
首先,你用浏览器打开该页面时,应该不会有任何错误。这说明浏览器加载页面对JS进行渲染解释时并没有去解释方法内部的实现,因为方法a()中我写了一行没有语法规则的字符串,如果刚才解析了必会报错。
然后你点击按钮test_b,你会发现b()方法顺利调用了,没有出现问题。
接着,你点击按钮test_a,发现并没有alert(a),而是报了'sadasd' 未定义的错误。可见js方法中的内容是在方法被调用时去解析的。
到此,我解释下方法c(),d()的设计用意。
方法c(),我是模拟了本文开头提到的ajax回调方法中向页面div的innerHTML添加js方法定义这种场景。通过添加按钮test_c,触发方法c(),在方法c()中向id为“test1”的div的innerHTML添加了方法z()的定义,代码仅仅是非常简单的alert("z")。然后试图调用z(),这也正是我当时遇到的错误。
方法d()是对c()的结论一个再次论证,如果我在d()中清除了div“test2”中的innerHTML,即删除了方法b()的定义,那我还能调用b()嘛?
思考一分钟,预测下你的结果?
然后你义无反顾的点击按钮test_c,发现z is not defined的错误。
如果此时你通过firebug去查看“test1”div,你可以看到存在:
<script>function z(){alert("z");}</script>
但是为什么会报z is not defined呢?
接着你疑惑着去点击test_d,结果b调用又成功了....alert了b.
我的理解是这样的(纯属个人通过实验的结论):
1.浏览器在第一次加载页面后将所有<script>标签内的js放入浏览器中属于js的上下文内存栈,然后解析并执行所有<script>标签内的js全局脚本。(这也就是为什么在后面通过事件往页面innerHTML添加的js方法被认为是is not defined的原因,而我们删除的b()却还可以调用)
2.在事件触发等原因造成方法被调用时,首先去上下文栈里查找该方法定义,找到的解释并执行该方法(所以a()在此时报错了),否则报XX is not defined的错误。
暂时做个实验记录,有时间再去看看具体浏览器对JS引擎的相关实现。
分享到:
相关推荐
C#与JAVASCRIPT函数的相互调用 C#调用JAVASCRIPT函数的调用 JAVASCRIPT调用C#函数的调用
实现JavaScript 动态加载事件
JavaScript在浏览器中被解析和执行时具有阻塞的特性,也就是说,当JavaScript代码执行时,页面的解析、渲染以及其他资源的下载都要停下来等待脚本执行完毕①。这一点是没有争议的,并且在所有浏览器中的行为都是一致...
用javascript代码调用delphi写的函数
javascript在浏览器中的性能,可以认为是开发者所面临的最严重的可用性问题,今天,自己看完高性能的javascript的加载和执行这一章,聊聊怎么解决js的加载顺序和执行的原理,下面话不多说了,来一起看看详细的介绍:...
ActionScript与JavaScript相互调用
JavaScript如何调用WCF,很实用
一个在HTML中使用Javascript的window.external调用C#内函数的示例程序。该方法可应用于网页程序开发中的网页-程序沟通,例如用C#的IHTMLWindow2.execScript替换HTML默认Javascript方法使其直接与C#传参、通讯。
java javascript 调用cmd命令
vbscript和javascript互相调用方法
_net中前台javascript与后台c#相互调用 - 前台javascript与后台c#相互调用
JavaScript调用WebService实例总结
JavaScript 函数调用 JavaScript 函数有 4 种调用方式。 每种方式的不同方式在于 this 的初始化。 this 关键字 一般而言,在Javascript中,this指向函数执行时的当前对象。 Note 注意 this 是保留关键字,你不能...
JAVASCRIPT在页面加载时的执行顺序[参考].pdf
JavaScript 调用wsdl示例,包含通过dot创建的ws示例
使用javascript调用webservice示例.pdf使用javascript调用webservice示例.pdf
使用ArcGIS API for JavaScript4.10加载高德地图和高德影像,通过扩展BaseTileLayer来自定义GaodeMapLayer模块。
xe7android手机调用javascript
从 XSLT 样式表调用 JavaScript