以下代码有点不明白
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?我知道可以通过传参解决,但是一直说不清楚其中机制,求大牛解答。
Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
ES6之前,Js中只有函数是具有块级作用域的,所以a中使用var声明的tag是在函数a作用域内的,而函数b执行时会在自己的作用域中找tag,找不到就会去外层找,直到全局对象上还没有就是
undefined,这里a和b不是包含关系,因此b自身没有tag时不会去a中找,而是去全局找,结果也没有,所以是undefined,如果你的b函数声明是在a内部的,你再调用就会打印出true了。js是词法作用域(除了this),也就是说,函数的作用域是在函数定义好时就已经确定好了。a函数是一个独立的作用域,有着自己的变量对象,b函数是一个独立的作用域,有着自己的变量对象,这两个作用域是平级的,其作用域链的上层为全局作用域。题主要是想让b函数能放到a内定义的tag变量的话,需要改变定义的方式,也就是将b函数内定义在a函数内,这样b的作用域链会包含a的作用域。@Lapsec 已经说得很清楚了,我提供一个别的思路。
在
a()里面的b()只是一个“调用”,不是本身,所以其“本身”所带的tag是未定义的因为函数的作用域链式在函数声明的时候就定义好的,而不是在函数调用的时候。虽然b是在a中调用的,而console.log(tag)这个函数是在b中执行的,它会在b中寻找变量tag,找不到就会到b的上一级作用域,也就是全局中寻找tag(因为b是在全局中声明的),还找不到就返回undefined。
如果把b声明在a中,就可以找到tag了,即:
function a() {
};
a();
@Lapsec 链接中的文章说this指向的作用域是在调用时确定,但实际测试结果显示貌似不是这样
func是在全局作用域下定义,调用是在scop.a中。但输出的结果是指向了window.
scop.a定义在scop中,调用是在全局作用域下调用,但输出的结果是指向scop,而非window.
所以this指向是在定义时决定的。
你这段代码运行出来的结果应该是报错才对。
如果你在函数外声明了var tag;才会输出tag is undefined。
说简单点,这就是个作用域的问题。
你在a函数体内声明了tag变量,b函数体内是访问不到的。
说复杂点,还需要扯到scope和lexical上。