JS函数名与变量名重名的问题

JS函数名与变量名重名的问题

由于JavaScript的预编译会导致变量声明提升,声明式函数整体提升,因此当函数名与变量名重名的时候将会产生问题。

变量以及变量表达式(包括函数的表达式声明)在预编译阶段都只是声明提升,而没有赋值,值都为undefined。

而声明式函数在预编译阶段将会整体提升。

而在编译过程中,提升也是有顺序的:参数 > 函数 > 变量

因此函数与变量的预编译遵循以下规则:

  1. 函数声明置顶;
  2. 变量声明置顶;
  3. 遇到同名时,变量声明比函数声明更优先(置顶);
  4. 变量不会重复声明;
  5. 直接变量声明时赋值,在预编译解析时,会拆成声明和赋值2个部分,声明会置顶,而赋值将保留在原来的位置;
  6. 声明的提升只会提升到当前作用域下的顶层,而不会提升到作用域之外。
  7. 预编译过程中形成的作用域链的查找顺序是由里向外,JS执行顺序是自上往下的。
  8. 当函数被声明在判断语句内部时,JS会将函数声明当成表达式(赋值声明),即不会提升
//变量或变量表达式声明提升
var a = 10;
//这相当于
var a;   //这就是发生在预编译阶段的变量的声明提升,在这个阶段变量只有声明,而没有赋值,为undefined
a = 10;  //这是在执行阶段,将会对变量赋值

//函数表达式
let fun  = function(){
    console.log('hello simon');
}
//这相当于
let fun; //这就是发生在预编译阶段的变量的声明提升,在这个阶段变量只有声明,而没有赋值,为undefined
fun = function(){   //执行阶段才会进行定义
   console.log('hello simon'); 
}
//声明式函数整体提升
var a = 10;
function fun(){
    var b = 11;
}
//这相当于
function fun(){
    var b; 
    b = 11;
}
var a;
a = 10;

题1

由于函数声明是整体提升的,因此下面代码中,a函数声明在前,而变量a赋值在后,因此a是一个变量,而不是一个函数了,a执行出错

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

//相当于
var a = function(){
    console.log(a);
};
a = 10;
a();  //将报错,此时a是一个变量了

题2

预编译过程中形成的作用域链的查找顺序是由里向外,JS执行顺序是自上往下的。因此下面代码中a = 1时,if的作用域中并不存在a变量,所以会将1赋值给全局中的a变量。

var  a = 0;
if(true){
    a = 1;  //作用域中不存在a变量,因此会通过作用域链向外查找,找到全局中的a变量,并将1赋值
    function a(){}  //这是函数声明,相当于定义了一个函数a,并给其分配了内存
    a = 21;  //此时作用域中已经存在了a变量(a函数),因此该赋值将直接赋值给作用域中的a而不是全局的a
    console.log('里面', a);  //21,由于作用域中存在a变量了,因此直接打印作用域中的a
}
console.log('外面', a);   //1,全局作用域中存在a变量,并赋值为1,因此打印1

//相当于
var a;
a = 0;
if(true){
    a = 1;
    function a(){}  //由于函数是定义在判断语句中,所以没有声明提升
    a = 21;
    console.log('里面', a)  //21
}
console.log('外面', a);   //1

题3

函数会整体提升,因此b函数会被提升到全局作用域中的顶部,而a函数被提升到b函数作用域顶部。注意函数是自上而下执行的

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();  //执行b函数后,内部函数a会声明,因此作用域内存在一个a变量(函数),a = 10会赋值给a函数,而不是全局中的a变量了
console.log(a);  //1  打印的是全局的a变量,内部的a变量无法获取到

猜你喜欢

转载自blog.csdn.net/qq_31947477/article/details/105745014
今日推荐