转载

javascript进阶系列专题:作用域与作用域链

字面意思,作用域是指变量和函数的作用范围,换言之,作用域决定了变量和函数的可见性和有效时间。javascript作用域是用函数来区分,与其他语言的大括号不同。

 for (var i=0; i<5; i++){     var mystring = "平底斜";     console.log(i);  } alert(mystring);//弹出"平底斜" 

这段代码在javascript中运行正常,在其他语言中就会报错。这是因为javascript的作用域是基于函数,而不是大括号。

作用域分为全局作用域和局部作用域。

有三种情况会出现全局作用域:

1、最外层定义的变量和函数

 var mystring = "平底斜"; function fun(){     alert("Hello World"); } 

变量mystring和函数fun()拥有全局作用域,在任何位置都可以直接调用。

2、未定义的变量

 function fun(){     var   a=b=0;     mystring = "平底斜";     console.log(mystring); } fun(); alert(b); 

变量mystring没有使用var进行变量声明,所以即使在函数内部也是全局变量。容易忽略的是变量b,看上去使用var进行了声明,实际上只对变量a进行了声明,等同于

 function fun(){     var a=(b=0); //自右向左赋值     mystring = "平底斜";     console.log(mystring); }  

一个JS文件中应该尽可能少的出现全局变量,最佳实践是使用var进行变量声明,并且在声明的同时进行赋值。

 function fun(){     var a=0, b=1, c=2; //等同于var a=0; var b=1; var c=2; } fun(); alert(c); //脚本报错,因为c是局部变量 

3、全局对象window

 var mystring = "平底斜"; console.log(mystring); console.log(window.mystring); console.log(window["mystring"]); console.log(this.mystring); console.log(this["mystring"]);//此处this就是window,针对this以后会专题讲解 

全局变量都可以看做window的属性,使用方法就如以上代码:可以用"."也可以用"[]"甚至可以省略window

局部变量只有一种情况:在函数内部声明的变量拥有局部作用域

 function fun(){     var mystring="平底斜"; //局部变量     console.log(mystring); } fun(); console.log(mystring); //脚本报错 

冷知识:

全局变量中,使用var声明与不使用var是有区别的,var声明的变量无法删除,未声明的变量可以删除。

 var mystring="平底斜"; newstring = "博客园"; delete mystring; delete newstring; console.log(mystring);  //"平底斜" console.log(newstring); //脚本报错 

作用域链由内向外查找变量,在内部找到变量便停止查找,否则往上一层作用域查找,直到最外层都没有找到变量则返回undefined

 var myscope = "平底斜"; function fun(){     var myscope = "博客园";     console.log(myscope); //"博客园" } fun(); 

上面这段代码,就是因为作用域链有内向外,先在函数内部查找myscope,找到了就直接返回该变量值,并停止查找。

易错点:

 var myscope = "平底斜"; function fun(){     console.log(myscope); //脚本报错     var myscope = "博客园";     console.log(myscope); //"博客园" } fun();  

声明变量会在当前作用域中置顶,又叫变量提升或者声明置顶。以上代码等同于:

 var myscope = "平底斜"; function fun(){     var myscope;     console.log(myscope); //脚本报错     myscope = "博客园";     console.log(myscope); //"博客园" } fun(); 

需要注意的是变量提升是在函数 定义 时发生,并不是在函数调用时:

 var myscope = "平底斜"; function fun1(){       console.log(myscope); } function fun2(){      var myscope = "博客园";      fun1(); }  fun2(); //"平底斜" 

如上,fun2()调用fun1()时,是先在fun1()中搜索myscope,找不到时再到父级作用域中查找。作用域的嵌套关系是在定义时产生,而不是在调用的时候。

正文到此结束
Loading...