我对Javascript渲染加载以及解释调用顺序的一点理解

原本在项目中的需求是这样的,向服务器提交一个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引擎的相关实现。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值