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