js同名变量问题

看了很多网上关于变量同名的问题,记录下自己的理解。

需要注意的问题

1.变量提升问题
所谓变量提升,在我理解看来就是变量的声明和赋值在不同的阶段完成,js在预解析的时候就会将函数的声明和赋值提升到代码最前部(即函数声明置顶比变量声明置顶更优先,但是在特殊情况下变量声明不会覆盖函数声明,后续会讲到),然后提升变量的声明,最后按照js的执行顺序去给变量赋值。看例子

var a = 111;
function a (){
  console.log('111');
}
console.log(a);

等价于

function a (){
  console.log('111');
}
var a ;
a = 111;
console.log(a);

结果都是111,这就是代码提升,不过有种特殊情况,看例子:

//代码一
function a(){  
  console.log(10);  
}  
var a;
console.log(a);

//代码二
var a;
function a(){  
  console.log(10);  
}  
console.log(a);

此时代码一和代码二的输出均为
ƒ a(){
console.log(10);
}
这是因为在预解析阶段变量只声明了,但未赋值,而函数不一样,它在预解析阶段就已经声明和赋值了,它的值就是函数这个对象,而且 js作为一个弱类型语言,是根据里面具体存储的值来判断其类型的,所以当console.log的时候其值还是函数,所以就会打印出具体的函数体。

2.作用域问题
作用域问题的原则就是局部优先整体,函数变量的查找是由内向外的,在找到了第一个同名变量后就直接使用,不再继续查找。此原则同样试用于函数(因为函数其实可以看做是引用类型的存储,其引用保存在栈,具体实现在堆中),例子:

var a = 1;
function b(){
  a = 2;
  var a = 3;
  console.log("b函数中的a为:",a);
}
b();
console.log("外层a为:",a);

上段代码执行结果为:

b函数中的a为: 3
外层a为: 1

首先咱们先进行变量提升,得到:

function b(){
  var a;
  a = 2;
  a = 3;
  console.log("b函数中的a为:",a);
}
var a ;
a = 1;
b();
console.log("外层a为:",a);

可以看到b函数中出现重名变量a,此时变量有声明,为局部变量,所有函数内部后续所有的关于a的操作都是局部的这个a,所以b内部的操作不会影响到外部的a。
再看一个复杂点的例子:

var a = 1;
function b(){
    a = 10;
    return;
    function a(){
        console.log(a);
    }	
}
b();
console.log(a);

变量提升(注意函数的声明提升)之后结果如下:

function b(){
    function a(){
        console.log(a);
    }	
    a = 10;
    return;
}
var a ;
a = 1;
b();
console.log(a);

在b中变量a(简称 b->a)被声明成了函数,也就是说此时 b->a 变成了局部变量,然后 b->a 又被赋值成 10,返回后局部变量销毁,不影响外层a,所以输出为1。

发布了2 篇原创文章 · 获赞 3 · 访问量 42

猜你喜欢

转载自blog.csdn.net/that_not_easy/article/details/105074380