[讨论]JavaScript中用var声明变量问题

webphoenix 2010-11-19 12:27:33
有下面几段段函数
1.

var a = 123;
function test() {
document.write(a);
}
test()


2.

var a = 123;
function test() {
document.write(a);
var a = 345;
}
test();


3.

a = 123;
function test() {
document.write(a);
a = 345;
}
test();


4.

a = 123;
function test() {
document.write(a);
var a = 345;
}
test();


这4段代码分别执行出的结果是
1. 123
2. undefined
3. 123
4. undefined

对于第2段代码相对于第1段就加了句 var a = 345;
为什么值就是undefined?

照理来说不是顺序执行的么,第2段应该在执行 document.write(a); 这个的时候还没有var a = 345;这句的,为什么却又偏偏起了作用了,难道 解释器先找到 var 这个再去执行代码?
...全文
98 点赞 收藏 11
写回复
11 条回复
webphoenix 2010年11月20日
谢谢各位,大致了解到了什么意思,谁有没有权威一点的文档说明啊
回复 点赞
hch126163 2010年11月19日
本文主要是讲预编译。

1. undefined
当需要判断一个变量是否为 undefined 时,直接用
Js代码

1. alert(om == undefined);

alert(om == undefined);


可能出错。因为 JS 如果引用未声明的变量,那么会出现JS错误,在上述例子中,如果 om 未曾声明,就会报 JS 错误。因此判断一个变量是 undefined,最好用这种方法
Js代码

1. alert( typeof om == 'undefined' );

alert(typeof om == 'undefined');



2. JS 中没有块作用域,在函数中声明的变量在整个函数中都可用(无论是在函数开头处声明还是末尾处声明),如
Js代码

1. function () {
2. alert(om); // 显示 undefined
3. var om = 'abc' ;
4. alert(om); // 显示 abc
5. }

function() {
alert(om); // 显示 undefined
var om = 'abc';
alert(om); // 显示 abc
}



3. JS 在函数执行前将整个函数的变量进行声明,无论这个变量的声明语句有没有机会执行,如
Js代码

1. function () {
2. alert(om); // 显示 undefined
3. if ( false ) {
4. var om = 'abc' ; // 此处声明没有机会执行
5. }
6. }

======================================================================

今天工作需要,搜索下JS面试题,看到一个题目,大约是这样的
Js代码

1. <script>
2. var x = 1, y = z = 0;
3. function add(n) {
4. n = n+1;
5.   }
6.
7. y = add(x);
8.
9. function add(n) {
10. n = n + 3;
11. }
12.
13. z = add(x);
14. </script>

<script>
var x = 1, y = z = 0;
function add(n) {
n = n+1;
  }

y = add(x);

function add(n) {
n = n + 3;
}

z = add(x);
</script>



问执行完毕后 x, y, z 的值分别是多少?

仔细看的人马上就知道了, x, y 和 z 分别是 1, undefined 和 undefined。

不过,如果将两个 add 函数修改一下,题目变为
Js代码

1. <script>
2. var x = 1, y = z = 0;
3. function add(n) {
4. return n = n+1;
5.   }
6.
7. y = add(x);
8.
9. function add(n) {
10. return n = n + 3;
11. }
12.
13. z = add(x);
14. </script>

<script>
var x = 1, y = z = 0;
function add(n) {
return n = n+1;
  }

y = add(x);

function add(n) {
return n = n + 3;
}

z = add(x);
</script>


那么这时 y 和 z 分别是什么呢?我马上想到是 2 和 4,不过结果却是 4 和 4。
这说明,在第一次调用 add 函数之前,第二个 add 函数已经覆盖了第一个 add 函数。原来,这是 JS 解释器的"预编译",JS 解析器在执行语句前会将函数声明和变量定义进行"预编译",而这个"预编译",并非一个页面一个页面地"预编译",而是一段一段地预编译,所谓的段就是一个 <script> 块。且看下面的代码
Js代码

1. <script>
2. function add(n) {
3. return n = n+1;
4.   }
5. alert(add(1));
6. </script>
7.
8. <script>
9. function add(n) {
10. return n = n+3;
11.   }
12. alert(add(1));
13. </script>

<script>
function add(n) {
return n = n+1;
  }
alert(add(1));
</script>

<script>
function add(n) {
return n = n+3;
  }
alert(add(1));
</script>



会分别弹出 2 和 4。

那么,将上面的题目再变换一下,如下
Js代码

1. <script>
2. alert( typeof addA);
3. addA();
4. function addA() {
5. alert( "A executed!" );
6. };
7. </script>
8. <script>
9. alert( typeof addB);
10. addB();
11. var addB = function () {
12. alert( "B executed!" );
13. };
14. </script>

<script>
alert(typeof addA);
addA();
function addA() {
alert("A executed!");
};
</script>
<script>
alert(typeof addB);
addB();
var addB = function() {
alert("B executed!");
};
</script>



执行结果是什么呢? 按照前面的知识,第一个 <script> 块执行正常,结果就是弹出 "function" 和 "A executed!" 的对话框。
那么第二个 <script> 块呢? 执行结果是弹出 "undefined" 的对话框后报 JS 错误,说 addB 不是一个 function。
有点出乎意料?呵呵,其实第一个 script 块中的 addA 一句是函数声明,当然进行了"预编译",但是第二个 script 块中的 addB 一句并非函数声明。只不过在执行这段 <script> 之前对变量进行了"预声明",因此一开始变量addB是存在的,只不过是 undefined 的(可参看http://eclipse07.javaeye.com/admin/blogs/484566 )。因此执行结果便如上面所示。

将题目再变化下,如下
Js代码

1. <script>
2. alert( typeof addB);
3. addB();
4. var addB = function addB() {
5. alert( "B executed!" );
6. };
7. </script>

<script>
alert(typeof addB);
addB();
var addB = function addB() {
alert("B executed!");
};
</script>


执行结果如何呢?
在 ff 下执行,与上面执行结果一样。打住,且在 IE6 下执行看看如何。
结果是弹出 "function" 和 "B executed!",一切正常。
Google 了一下,有人说这是 IE 的 BUG。

那么,请看下面的代码
Js代码

1. <script>
2. alert( typeof addB);
3. var addB = "variable" ;
4. function addB() {
5. alert( "function addB" );
6. }
7. alert(addB);
8. </script>

<script>
alert(typeof addB);
var addB = "variable";
function addB() {
alert("function addB");
}
alert(addB);
</script>


执行结果是"function"和"variable"。
JS解析器先预定义了 addB 变量为 undefined, 但是 addB 函数覆盖了此变量,因此一开始执行结果是 function,然后 addB 被赋值为 "variable",因此最后执行结果是 "variable",上面的代码即使变为
Js代码

1. <script>
2. alert( typeof addB);
3. function addB() {
4. alert( "function addB" );
5. }
6. var addB = "variable" ;
7. alert(addB);
8. </script>

<script>
alert(typeof addB);
function addB() {
alert("function addB");
}
var addB = "variable";
alert(addB);
</script>


结果也一样,这说明JS解析器先预声明变量,再预定义函数 。
小结一下:JS 在执行前会进行类似"预编译"的操作,而且先预定义变量再预定义函数。
回复 点赞
flyerwing 2010年11月19日
长见识了.
顶.
回复 点赞
ahead123zhan 2010年11月19日
加补充下
JS 预编译时变量为undefined

[Quote=引用楼主 webphoenix 的回复:]
有下面几段段函数
1.
JScript code

var a = 123;
function test() {
document.write(a);
}
test()



2.
JScript code

var a = 123;
function test() {
document.write(a);
var a = 345;
}
test();



3.
……
[/Quote]
回复 点赞
ycproc 2010年11月19日
回复 点赞
slxliuxingbing 2010年11月19日
js在执行的时候会把当前的作用域的变量全部提前并设置在为 undefined

我去面试都不知道遇到过多少次了

baidu 搜索 javascript 预编译
回复 点赞
碧海情天-赵亮 2010年11月19日
或者看看这个
var a = 123;
function test() {
document.write(a);
a = 345;
document.write(a);
}
test();
回复 点赞
cxhzqhzq 2010年11月19日
[Quote=引用 1 楼 hch126163 的回复:]

是命名冲突了!

a = 123;
function test()
{
alert(window.a);
var a = 345;
}
test();

这样可以正确弹出123!

test();调用方法前,test 方法虽然没有执行,但是浏览器对他做了解析!
function test() {
document.write(a);
var a =……
[/Quote]
很给力的解释。
回复 点赞
TearsStoneJava 2010年11月19日
顶!
这个主要就是js中变量的规则:
全局变量,局部变量!
js不是java,它在文件加载时就已经把变量加载了!
回复 点赞
zougm 2010年11月19日
[Quote=引用 1 楼 hch126163 的回复:]

是命名冲突了!

a = 123;
function test()
{
alert(window.a);
var a = 345;
}
test();

这样可以正确弹出123!

test();调用方法前,test 方法虽然没有执行,但是浏览器对他做了解析!
function test() {
document.write(a);
var a =……
[/Quote]
正解
回复 点赞
hch126163 2010年11月19日
是命名冲突了!

a = 123;
function test()
{
alert(window.a);
var a = 345;
}
test();

这样可以正确弹出123!

test();调用方法前,test 方法虽然没有执行,但是浏览器对他做了解析!
function test() {
document.write(a);
var a = 345;
}
你在函数内部 声明了一个变量a,所以这里会执行 函数内部的变量a,而不是全局的变量a!
而执行 document.write(a);时,局部变量a 还没有声明所以是 undefined!


1和3,你没有在函数内声明变量,是使用的全局变量!当然是允许的!


回复 点赞
发动态
发帖子
JavaScript
创建于2007-09-28

5.1w+

社区成员

22.3w+

社区内容

Web 开发 JavaScript
社区公告
暂无公告