js中词法作用域和函数调用位置的疑惑

var a=3;
 function kk(){
 console.log(a)
 }
 var a=2;
 kk();//打印值为2

初学js,上面的代码我以前理解没问题,后来看了词法作用域后我就不能理解了。
我对词法作用域的理解是,你在编写代码的时候,作用域就定好了。
用上面代码解释我的想法:
执行kk()的时候,先查询kk自己局部变量有没有a值,没有的时候在全局变量里找;
这时以我对词法作用域理解,查找a全局变量的时候,只能**声明kk函数以上的地方找**,所以值应该是3。而**不应该在kk()调用位置**以上找,但是结果确实在调用位置上查询到a的变量为2。
是我对词法作用域的理解有偏差吗

就近原则:下面的var a=2;
在瀑布式加载时会替换之前的a值.

var a=3;
var a=2;

js并不认为重复声明变量a是错误,而是把第二次的声明忽略只剩下赋值。
你的理解没错,kk()用的就是那个变量a,只不过变量的当前值已经改变了啊。
你总不会认为kk()只会取初始值吧?

谁和你说 声明kk函数以上的地方找...的。js是解释执行的,执行了a=2后再执行kk(),那不是2是什么。。

需要注意的是用var申明的变量在其作用域内会提升并且赋值为undefined



    alert(a)//undefined
    var a = 3;
    alert(a)//3
    function kk() {
        console.log(a)
    }
    var a = 2;
    kk();//打印值为2

下面给a赋值为2 所以上面的3倍覆盖了

换一个简单粗暴的说法。函数只要是通过function xx(){} 声明的,都会有一个函数声明提升,这样,无论函数在哪声明,都不重要,重要的是你在哪里调用的。
也就是说你可以把函数声明全部放到文件的最上面和最下面,都没有任何影响。

 function kk(){
 console.log(a)
 }
var a=3;
 var a=2;
 kk();//打印值为2  看明白没有,重复声明,就是赋值,最后的赋值就是2 或者这样



var a=3;
 var a=2;
 kk();//打印值为2  

  function kk(){
 console.log(a)
 }