JavaScript 中,变量可以在使用后声明,也就是变量可以先使用再声明。
以下两个实例将获得相同的结果:
<script>
x = 5; // 变量 x 设置为 5
elem = document.getElementById("demo"); // 查找元素
elem.innerHTML = x; // 在元素中显示 x
var x; // 声明 x
</script>
<script>
var x; // 声明 x
x = 5; // 变量 x 设置为 5
elem = document.getElementById("demo"); // 查找元素
elem.innerHTML = x;
</script>
- 下面代码条件语句if(!foo)并不会执行,为什么foo会被赋值为10:
var foo = 1;
function bar() {
if (!foo) {
var foo = 10;
}
alert(foo);
}
bar();
- alert输出了1:
var a = 1;
function b() {
a = 10;
return;
function a() {}
}
b();
alert(a);
C语言的一个例子:
#include <stdio.h>
int main() {
int x = 1;
printf("%d, ", x); // 1
if (1) {
int x = 2;
printf("%d, ", x); // 2
}
printf("%d\n", x); // 1
}
程序依次输出了1,2,1; 因为在C语言中,我们有块级作用域(block-level scope)。在一个代码块的中变量并不会覆盖掉代码块外面的变量。
JavaScript的一个例子:
var x = 1;
console.log(x); // 1
if (true) {
var x = 2;
console.log(x); // 2
}
console.log(x); // 2
输出的结果为1,2,2 if代码块中的变量覆盖了全局变量。
那是因为JavaScript是一种函数级作用域(function-level scope)所以if中并没有独立维护一个scope,变量x影响到了全局变量x
- JavaScript实现一种类似块级作用域的效果, 闭包:
function foo() {
var x = 1;
if (x) {
(function () {
var x = 2;
// some other code
}());
}
// x is still 1.
alert(x);
}
foo();
Hoisting in Javascript
在代码运行前,函数声明和变量定义通常会被解释器移动到其所在作用域的最顶部
- 1
function foo() {
bar();
var x = 1;
}
被代码解释器编译完后,将变成下面的形式:
function foo() {
var x;
bar();
x = 1;
}
- 2
function foo() {
if (false) {
var x = 1;
}
return;
var y = 1;
}
function foo() {
var x, y;
if (false) {
x = 1;
}
return;
y = 1;
}
变量的上升(Hoisting)只是其定义上升,而变量的赋值并不会上升。
创建一个函数的方法有两种,一种是通过函数声明function foo(){}
另一种是通过定义一个变量var foo = function(){}
这两种在代码执行上的区别:
function test() {
foo(); // TypeError "foo is not a function"
bar(); // "this will run!"
var foo = function () { // function expression assigned to local variable 'foo'
alert("this won't run!");
}
function bar() { // function declaration, given the name 'bar'
alert("this will run!");
}
}
test();
foo()调用的时候报错了,而bar能够正常调用
var foo首先会上升到函数体顶部,然而此时的foo为undefined,所以执行报错。而对于函数bar, 函数本身也是一种变量,所以也存在变量上升的现象,但是它是上升了整个函数,所以bar()才能够顺利执行。
开头的两段代码:
var foo = 1;
function bar() {
if (!foo) {
var foo = 10;
}
alert(foo);
}
bar();
实际为:
var foo = 1;
function bar() {
var foo;
if (!foo) {
foo = 10;
}
alert(foo);
}
bar();
var a = 1;
function b() {
a = 10;
return;
function a() {}
}
b();
alert(a);
实际为:
var a = 1;
function b() {
function a() {}
a = 10;
return;
}
b();
alert(a);
改变了function a的值,从函数变为数值10,其实函数本身也可看做变量的定义,function 和 var 返回的类型不同而已。