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,找不到时再到父级作用域中查找。作用域的嵌套关系是在定义时产生,而不是在调用的时候。

原文地址:https://www.cnblogs.com/newgold/p/javascript_scope.html