有关javascript的全局变量的问题,请问下面第一个输出s为什么结果是undefined,这里访问不到全局变量s吗?

<scriptlanguage="JavaScript">vars="1";functionshow1(){document.write(s+"<br>");vars="... <script language="JavaScript">
var s="1";
function show1() {
document.write(s+"<br>");
var s="3";
document.write(s+"<br>");
}
show1();
</script>
恕在下愚钝,各位回答我觉得都不大对啊,
请问如果把程序改成如下,为什么又能访问全局变量了呢?也就是说原先的为什么不能访问到全局变量,这里又行了。在内存中,全局和局部变量虽然都是s,但他们占得内存应该是不同的啊,请“没有响应m2”解释一下吧
var s="1";
function show1() {
document.write(s+"<br>");
}
show1();
展开
 我来答
soiha_891
2012-05-23 · TA获得超过743个赞
知道小有建树答主
回答量:222
采纳率:100%
帮助的人:115万
展开全部
js里面,函数作为作用域范围,在这个范围里,首先完成的过程是变量初始化和声明。也就是说,show1执行之前,内部变量已经初始化,初始化的值都是undefined。所以,第一write的s等于undefined。
js的运行顺序
步骤1. 读入第一个代码段(js执行引擎并非一行一行地执行程序,而是一段一段地分析执行的)
步骤2. 做语法分析,有错则报语法错误(比如括号不匹配等),并结束
步骤3. 对var变量和function定义做“预解析”(永远不会报错的,因为只解析正确的声明)
步骤4. 执行代码段,有错则报错(比如变量未定义)
你的例子中,一个function可以看成一个独立的作用域空间,是一个独立的代码片段,执行是,第一步是变量预解析,所以,不管s在全局变量是否存在,你那个function内部执行的时候,局部变量s已经声明,初始化了,在函数执行执行,变量会提前声明的,预解析阶段,所有变量都是undefined。你的代码实际效果是这样的:

var s;
s="1";
function show1() {
var s;
document.write(s+"<br>");
s="3";
document.write(s+"<br>");
}
show1();
如果这样写,就很清楚了吧,js就是这样分析代码的。
追问
soiha_891您好!
您说的我还是不大清楚,可以这样理解吗?第一段show因为访问未被定义的s,所以是undified,在这里其实还是局部变量对全局变量进行了覆盖。
而第二段show在分析时,js认为s是已经被定义的全局变量s。对吗?
也就是说不可以在同一个函数中同时访问到全局变量s和局部变量s,是吗?
谢谢
追答
不是说覆盖,js里面变量访问是逐步的,作用域分局部很全局的区别,一个函数形成一个局部作用域范围。在show1函数里面,构成一个作用域范围,这个作用域里面通过var 声明了s这个变量,所有,首先查找到的s是局部作用域里面的s,如果s在函数show里面没有声明,语法解析过程,会往上一层的作用域中查找,如果找到了s,就使用那个全局的变量s。
全局的s还是全局的,他们是两个不同的东西,一个是挂载在全局global对象上,一个是在函数内部,一个局部的s。就像,在中国有一个地方叫A,在湖南生也有个地方叫A,那么,在湖南,我们说A通常就是只湖南的A,在全国范围,A就是全国的A。 可以这么理解:第一个s是window.s,第二个sshow函数执行的时候,形成一个闭包对象,vo = {s: ''}。
这些是js基本原理,这样比较专业的问题,最好还是在知乎或者51js上去问比较好。
归结到底还是变量查找顺序的问题。你可以想象一个盒子,盒子相互嵌套,最外面那个盒子是全局的对象,里面上挂载着所用的全局变量,在浏览器端,这个大盒子就是window对象,一个全局的变量实际上是window对象上一个属性,比如全局的s,可以这样访问,window['s']。每次声明一个函数,在大盒子里面嵌套一个盒子,这个盒子有自己的属性,也就是局部变量,访问变量的时候,首先在自己的盒子里面查找,找不到就跑外面去找。这里有一个规则,盒子里面可以访问盒子外面的变量,外面无法访问里面。查找层级越高,查找速度越慢,所以会有这么一种写法
(function(win, undefined){
})(window, undefined);
匿名函数的执行,形成一个对全局封闭的盒子,这样,这个匿名函数内部不会干扰全局对象,防止和其他代码冲突。另一方面,把window和undefined传递到匿名函数,这样,在匿名函数内部访问win和undefined就快一些了,查找减少了一层。
扯远了。这个问题还是蛮有意思。不知道有没有说清楚。
很好cai
2016-12-09 · TA获得超过153个赞
知道小有建树答主
回答量:123
采纳率:66%
帮助的人:28万
展开全部

综合了一下各位朋友的答案,终于取到了值。m,mm是两个全局变量。

虽然他们是全局变量,但是必须经过一次转换(赋值)才能传到另外一个函数。

有需要的朋友一定要认真看图,有注释的。

已赞过 已踩过<
你对这个回答的评价是?
评论 收起
llluterxk
2012-05-22 · TA获得超过1747个赞
知道小有建树答主
回答量:1329
采纳率:0%
帮助的人:765万
展开全部
s是在外边定义了一次,但是在调用show1()时,先会对变量(方法)等进行一次检查。如果该内存块内有与全局变量同名的变量。全局变量失效,会调用show1()函数内的局部变量;

而在show1()中,s是先调用 后声明的。所以浏览器认为是未声明的
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
召秋梵悌p1
2012-05-22 · TA获得超过2282个赞
知道小有建树答主
回答量:616
采纳率:80%
帮助的人:675万
展开全部
上面几位说的都不对,呵呵。第一个s是undefined, 和局部变量、全局变量没有任何关系,而是和document.write(...)这个方法有关。可以很简单的举例证明:
把document.write(...)改成alert(...)。你会发现,两次弹出的信息都是有值的。

一旦调用document.write,会直接清除掉原来页面的内容,打开一个新文档写入内容,以至于原来页面中定义的变量啊、标签啊等,通通都没有了。(所以我们有时候会发现 document.getElementById('xxx')突然就返回null了)。

满意请采纳。
追问
我试过了,换成alert不行
追答
我错了,感谢楼主,学到新东西了。
我同意llluterxk的说法
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
没有响应m2
2012-05-22 · TA获得超过8387个赞
知道大有可为答主
回答量:7579
采纳率:33%
帮助的人:3432万
展开全部
这个只能说javascript不像java这样的编译型的编程语言一样能自动识别变量的作用域.
javascript不能用函数里的变量来覆盖全局变量
如果一定要这么写的话那就改成
<script language="JavaScript">
var s="1";
function show1() {
document.write(window.s+"<br>");
var s="3";
document.write(s+"<br>");
}
show1();
</script>
追问
感觉你的答案是靠谱的,可是我不太明白。再说的详细一些吧。就是说我在同一个函数中,既想引用全局变量s又想引用局部变量s。“javascript不能用函数里的变量来覆盖全局变量”是什么意思啊?谢谢
追答
....其实javascript不能用函数里的变量来覆盖全局变量是我说错了........后来我又测试了下可以覆盖
不过你上边的那个document.write(s+""); 这个s应该是被浏览器当成了还没有定义的变量
你在下边定义了 var s=3 的缘故....
如果你把 var s=3 放到 document.write(s+""); 就能正常输出
不过你这问题属于只要用点心就能完全避免发生的...至于具体原理这个真不好说 研究它也没什么意义
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 更多回答(3)
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式