作用域和预解析
个人理解:
首先是作用域:
作用域分为全局和函数作用域 (在es6中还存在块作用域,let定义变量时,可以自行了解).那么全局也就是window,我们定义变量时是针对window定义的变量在任何地方都是存在并且可以调用的。
相对应的就是在函数中定义变量时是针对函数来说的局部变量,在函数外是无法找到的。并且在函数嵌套时,你要明白只能从内向外寻找变量,不能从外向内寻找变量。
<p> function a(){
<p> console.log(c);
<p> function b(){
<p> var c=1;
<p> }
<p> }
<p> a();
结果为undefined
function a(){
var c=1;
function b(){
var c=3;
console.log(c);
}
b();
console.log(c);
}
a();
结果为3 1 因为b内是 var 重新定义的c 这个c和函数a中的c完全没关系 当我们省略函数b中的var 那么会得到两个 3
理解函数内部后,全局变量和局部变量更容易理解了 window就是一个大环境 里面的函数都可以调用变量而外面的不能调用函数内部的变量
var d=1;
function a(){
var c=1;
function b(){
var c=3;
console.log(c);
}
b(); //执行b函数
console.log(c);
console.log(d);
}
a(); //结果3 1 1 这里a函数内找不到d就会继续往上寻找
console.log(c);
//undefined
理解之后我们来讲预解析:预提前的意思,window也就是全局中的变量和函数都在进行浏览器解析的时候,都会在最开始的地方先将变量和函数定义出来 也叫做变量提升 未定义的结果也就是undefined;定义是定义 赋值是赋值 在没有赋值之前我们打印它 那么就是undefined 赋值之后就是我们所想要的结果。函数也一样
console.log(d); //undefined
var d=1; //也就是说在d没有声明赋值之前 打印d会是undefined
console.log(a());//在函数声明前先打印函数a()
var d=1;
function a(){
var c=1;
function b(){
var c=3;
console.log(c);
}
b(); //执行b函数
console.log(c);
console.log(d);
//return c; //这里最后的结果就是c的值为1
}
//结果是3 1 undefined undefined
为什么呢 先执行a里面的内容 3 1 undefined 因为我们在d赋值之前执行函数所以d虽然被定义了但是没有赋值 所以是undefined 而最后一个undefined 是a()函数的返回值 因为没有renturn的函数的返回值都是undefined 当我们给return 那么结果就会改变
刚才说的是全局的预解析 那么在函数里也是同理,如果在函数里面的定义变量赋值之前打印它 也是undefined 就像这样
function a(){
console.log(c);
var c=1;
}
a();
结果为 undefined
function a(n){ //函数的参数 也是函数的局部变量
if(n){
s="ifscope";
for(var/* let*/ i=0;i<10;i++) ;
}
console.log(i); //如果let定义i 我们就会看到i没有定义
}
a(true); //结果是10
console.log(s); //这里的s是ifscope
这里就很容易帮助我们理解在循环外打印这个 s 在函数中没有使用var 或者let定义 ,会d自动被定义为全局变量所以我们才能在打印s的时候看到结果,如果使用了let或者var 就会看到报错没有定义。另外如果用let来定义i,我们在循环外打印i也会看到未定义的报错,这就能看出let的块作用域只针对循环内部
在es6中已经不支持变量提升了,会直接报错。