在coding过程中遇到过下面的情况:
1 var test1 = function(){ 2 var c=4; 3 test2(); 4 }; 5 6 var test2 = function(){ 7 console.log(c); 8 }; 9 10 test1();
思考一下,7行会conasole出什么?4 吗?实际上却是 c is not defined。
而当代码如下的时候,
1 var test1 = function(){ 2 var c=4 3 var test2 = function(){ 4 console.log(c); 5 }; 6 7 test2(); 8 }; 9 10 11 test1();
或者代码如下
1 var test1 = function(){ 2 c=4 3 test2(); 4 }; 5 6 var test2 = function(){ 7 console.log(c); 8 }; 9 10 test1();
console 出的就是4。
这是为什么呢?
首先,让我们明白两个知识点:
1、js作用域:作用域就作用范围分为全局作用域和局部作用域。
A、全局作用域:从定义变量的位置开始到本源文件结束。其中 a 就是一个全局变量,作用范围全局,所以在 4 和 6 都可以 console 出 3.
1 var a = 3; 2 3 var test3 = function(){ 4 console.log(a); 5 var test4 = function (){ 6 console.log(a); 7 }; 8 test4(); 9 }; 10 11 test3();
B、局部作用域。在本函数范围内。通俗一点说,局部变量只能在定义它的函数内部使用,而不能在其它函数内使用这个变量。
1 var test3 = function(){ 2 console.log(a); 3 var test4 = function (){ 4 var a = 3; 5 6 console.log(a); 7 }; 8 test4(); 9 }; 10 11 test3();
我们把上一个代码中的 var a = 3;移到第四行,就会出现 2 行的console 中的 a 没有定义的报错,这是因为 a 是在 test4 这个函数中定义的,所以外部的函数test3不能访问包裹在里面的 test4 定义的 a。
这就又出现了一个概念:内部函数可以访问外部函数的变量,外部不能访问内部函数的变量。
1 var test3 = function(){ 2 var a = 3; 3 console.log(a); 4 var test4 = function (){ 5 console.log(a); 6 }; 7 test4(); 8 }; 9 10 test3();
我们再把 var a = 3; 移到第2行,那么就可以正常打出 3 行和 5 行的console。说明 test4 可以访问外部的 test3 的定义的变量 a。
2、 var 与不 var 的区别。有var声明的是局部变量,没var的声明的是全局变量。
好了 ,现在回到最开始的问题上,再贴一次代码,方便瞅。
1 var test1 = function(){ 2 var c=4; 3 test2(); 4 }; 5 6 var test2 = function(){ 7 console.log(c); 8 }; 9 10 test1();
这个是console不出来的,原因是什么呢?
总共有两个函数 test 1 和 test 2 ,各有各的局部作用域,其中 var c = 4 在 test 1 中,而非在 test 2 中,所以 test 2 不能够调用在 test 1 中的变量 c。那你会说我再第三行调用了 test 2 这个函数啊?那是因为 test2();是个指针,指向位于下方的 test 2 函数,但是指针只能调用对象的内存地址,你可以使用它的值,但你不能改变或调用其内部实现时的任何变量。简单来说,就是你只可以调用这个函数的值,但不能改变它,不能影响它。
而当没有 var 声明的时候,也就是第三段代码:
1 var test1 = function(){ 2 c=4 3 test2(); 4 }; 5 6 var test2 = function(){ 7 console.log(c); 8 }; 9 10 test1();
虽然没有 var 的字样,但并不代表它没有声明,只不过这个时候声明了一个全局变量,他的作用域是全局。所以下方的 test 2 函数可以调用 c = 4。
再或者代码如第二段:
1 var test1 = function(){ 2 var c=4 3 var test2 = function(){ 4 console.log(c); 5 }; 6 7 test2(); 8 }; 9 10 11 test1();
同理,不看 test 1 那么 就相当于
1 var c=4; 2 var test2 = function(){ 3 console.log(c); 4 }; 5 6 test2();
c 就是 全局变量,test 2 当然可以使用 c 啦~ 加上 test 1 之后,也就是对于 test 2 来说 test 1 函数内声明的变量 是个全局变量,在整个 test 1 中都可以调用。
完。