变量声明提前

js中只有2种作用域:全局作用域和函数作用域,没有块级作用域。循环内定义的变量,相当于定义在循环所在的空间,出了循环仍可继续使用。

console.log(temp);      //不会报错,循环体没有块级作用域,循环内的变量相当于直接声明在当前代码块的最前面
for(var i=0;i<10;i++){
    var temp;        //除了第一次为undefined外,其余循环时都会有值(重复声明变量但不赋值并不会覆盖原有变量);如果已经有同名变量,再次声明并不会再新建。每次循环只是赋值不同,并不会重新创建一个新变量。
    for(var j=10;j>0;j--){
        temp=j;
    }
}

 声明提前(Hoisting):在函数正式执行前,提前预读var声明的变量名和function声明的函数名及函数体,并将其集中到【当前作用域】的顶部创建。变量的赋值仍等运行到所在行时执行。

函数定义时,不会读取函数内部的内容,只有被调用时才会。所以闭包一定要等外部函数运行后内部函数的作用域才会被增长。

函数声明和变量声明一样也会提前到函数体的最前面,同名时刚进入函数时,只有同名的函数,因为变量还未赋值。运行后再看该名字最后被赋什么值。

变量仅仅是重复声明不会改变原有变量的值,不产生任何影响。

function hoisting(){
    a=5;
    var a;
    console.log(a);       //输出5,window.a仍为undefined,进入函数时,其作用域内已经有变量a了
}

function hositing2(){
    console.log(a);     //不会报错,变量提升,但赋值仍在原来所在行,输出undefined
    var a=5;
}

//函数声明提升
function test(){
 console.log(a);    //进入函数时,未赋值的变量a被函数声明提前赋值,此时a为函数
    var a=1;        //标识符a赋值为1
 function a(){...}    //不再运行函数定义,标识符a不会重新被赋值,仍然为1
  console.log(a);  
}()
//等同于如下
function test(){
  var a;
  function a(){...}
  console.log(a);
  a=1;
  console.log(a);
}
//函数声明提前,所以标识符是有值的 var test=5; test(); //会报错,开始执行时test指代函数,后面的赋值覆盖了同名函数,调用会报错。 function test(){ console.log("声明提前") }

 在函数中,形参是局部变量,相当于在函数的第一句就var一个变量并赋值,进入函数时就有值,函数体内和形参同名的变量声明只是重新给形参赋值而已,并不会创建新的变量。

function g(arg){
  var arg=10;
  console.log(arg,arg===arguments[0]);    
}
g(5);    //输出10,true

 

posted @ 2017-02-09 23:26  开发之路  阅读(546)  评论(0编辑  收藏  举报