首页 > JS函数作用域

JS函数作用域

以下代码有点不明白

function a(){
    var tag=true;
    b();
}
function b(){
    console.log(tag)
}
a();

执行a函数,那么就是先声明tag=true,然后执行b,按照把b中的console.log(tag)这句语句搬进a中替代b()的话,那么tag应该是可以打印出的,为什么tag为undefine?我知道可以通过传参解决,但是一直说不清楚其中机制,求大牛解答。


function a(){
    var tag=true;//此处申明的只是局部变量,而非window.tag
    b();//此处执行b的内容
}
function b(){
    console.log(tag) //tag相当于window.tag,
}

a()//所以执行结果是undefined


//--------我们不妨把程序修改一下

var tag = 'b' //申明了window.tag变量
function a(){
    var tag='a';//此处申明的只是局部变量,而非window.tag
    b();//此处执行b的内容
}
function b(){
    console.log(tag) //tag相当于window.tag,
}

a()//所以执行结果就是'b'

ES6之前,Js中只有函数是具有块级作用域的,所以a中使用var声明的tag是在函数a作用域内的,而函数b执行时会在自己的作用域中找tag,找不到就会去外层找,直到全局对象上还没有就是undefined,这里a和b不是包含关系,因此b自身没有tag时不会去a中找,而是去全局找,结果也没有,所以是undefined,如果你的b函数声明是在a内部的,你再调用就会打印出true了。


因为函数的作用域链式在函数声明的时候就定义好的,而不是在函数调用的时候。虽然b是在a中调用的,而console.log(tag)这个函数是在b中执行的,它会在b中寻找变量tag,找不到就会到b的上一级作用域,也就是全局中寻找tag(因为b是在全局中声明的),还找不到就返回undefined。
如果把b声明在a中,就可以找到tag了,即:
function a() {

var tag = true;
b();
function b() {
    console.log(tag);
};

};
a();


你这段代码运行出来的结果应该是报错才对。
如果你在函数外声明了var tag;才会输出tag is undefined。

说简单点,这就是个作用域的问题。
你在a函数体内声明了tag变量,b函数体内是访问不到的。
说复杂点,还需要扯到scope和lexical上。


这是this的指向问题。
在函数里面,this的指向是window。
在a里面调用b,b的this此时指向window,没有tag这变量,输出就是undefined了

搜了下相关文章:http://web.jobbole.com/85198/


js是词法作用域(除了this),也就是说,函数的作用域是在函数定义好时就已经确定好了。
a函数是一个独立的作用域,有着自己的变量对象,b函数是一个独立的作用域,有着自己的变量对象,这两个作用域是平级的,其作用域链的上层为全局作用域。题主要是想让b函数能放到a内定义的tag变量的话,需要改变定义的方式,也就是将b函数内定义在a函数内,这样b的作用域链会包含a的作用域。


@Lapsec 已经说得很清楚了,我提供一个别的思路。
a()里面的b()只是一个“调用”,不是本身,所以其“本身”所带的tag是未定义的


@Lapsec 链接中的文章说this指向的作用域是在调用时确定,但实际测试结果显示貌似不是这样

var 
    func = function(){
        console.log(this);
    },
    scop = { 
        'a':function(){
            func();
            console.log(this);
        }
    };
    scop.a();

func是在全局作用域下定义,调用是在scop.a中。但输出的结果是指向了window.
scop.a定义在scop中,调用是在全局作用域下调用,但输出的结果是指向scop,而非window.
所以this指向是在定义时决定的。

【热门文章】
【热门文章】