变量声明提前
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
以上皆为个人理解,如有错误之处,欢迎留言指正。