变量作用域、声明提前、作用域链

恩,快要下班了,我先捡重要的说奥

1、首先了在函数体内 "局部变量" 优先于 "全局变量" ,这其实算是废话了

var a = 'aa';
        var test = function(){
            var a = 'bb';
            alert(a);
        }
        test();

2、js无块级作用域,至于这块级作用域,大家可以想想C语言,PHP之类,"{}"之中定义的,外面是看不到了,但是JS就不是了,例如

for(var i = 0; i < 5; i++){

        }
        alert(i);

3、声明提前(此处有读者发现错误,现在进行改正)

var a = 'aa';
function test(){
  alert(a);//undifined
  var a = 'aa';
}

上述是因为声明提前所致,js执行分为两段,第一段先解释,第二段才开始执行, 由于局部变量优先级高于全局变量,所以函数本身先回访问局部变量中的'a',在调用'alert'之前局部变量中的'a'为'undefined',,上述代码解释后的结果等价于下方


var a = 'aa';

function test(){
var a = undefined;
  alert(a);
  a = 'aa';
}

上面那段代码其实还有更加深奥的解释,比如‘汤姆大叔’这篇 深入理解JavaScript系列(2):揭秘命名函数表达式 

4、作用域链

又来到了这个高大上的话题,什么是作用域链?

每一段js代码(全局代码和函数)都有一个与之关联的作用域链,这个作用域链是一个对象列表或者链表,这组对象定义了这段代码‘作用域中的变量’,当js需要查找变量x的值得时候(变量解析),它会从链的第一个对象开始查找,如果这个对象有个一个名为x的属性,则直接使用这个属性的值,如果不存在x属性,js会查找链上的下一个对象,如果仍然没有则继续下一个对象,以此类推。如果该链上没有任何一个对象用于x属性,那么就认为该段代码作用域链上不存在x,最终抛出一个引用异常错误

下面我们用一段代码来阐述这个话题

var a = 'aa';
var test = function(){
   alert(a);  
}

var test1 = function(){
  var a = 'bb';
  test();
}

test1();

上面一段代码虽然在函数'test1'里面重新定义了变量'a'但是函数 'test'仍然弹出'aa', 这个就可以用'作用域链'理论来解释这个现象

对于函数'test'而言,它的作用域链应该是 'global' 全局作用域对象和函数'test'本身作用域对象,'global'全局作用域对象在外层,'test'本身作用域对象在内层,'global'全局作用域对象上有一些属性,其中就包括变量'a'、'test'、'test1',当然其内部机制肯定有指定该变量是什么类型、什么值的地方,这里我们暂且不去探讨。以此类推,函数'test1'的作用域链是'global'链再加上其本身作用域对象,其本身作用域对象属性中包括变量'a'。那么在执行函数'test'的时候,'test'自然会在自己的作用域链上查找变量属性,而不会跑到'test1'的作用域链上查找属性,这时'test'的作用域链上刚好有'a'属性,其值为'aa'。 还记得我当初那篇"javascript中的闭包,超简单论述,保证小学生必懂" 文章吗,里面也有有关作用域链和闭包的解释。另外,还有一篇比较高深的,"汤姆大叔" 的 "深入理解JavaScript系列(14):作用域链(Scope Chain)" ,可以去瞅瞅,不过是否能懂,就看造化了!

鄙人才疏学浅,有不足之处,欢迎补足!

原文地址:https://www.cnblogs.com/painsOnline/p/5103294.html