今天突然想到个问题,如果在方法中访问一个将来会存在的变量,能不能成功,如下:
function A() {
console.log(val);
}
function B() {
var val = 123;
A();
}
B();//报错,val未定义
按我的想法,A在运行时,首先在内部找不到val,必定会沿着作用域链往上找,它会在B方法里找到一个val,应该不会报错才对。如果改成这样:
var val = 456;
function A() {
console.log(val);
}
function B() {
var val = 123;
A();
}
B();//456
这次val输出的是456,说明A在运行时确实沿着作用域链找到了最外层的val,那为什么会无视掉B中的val呢。
难道A方法在定义的时候就必须保证val是存在的?js不是非编译的么。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
B和A在作用域链上是平级关系,并不会因为B调用了A就变成A的父作用域,除非A在B里面声明
你下面那段示例代码中的两个
val是完全不同的两个变量,没有任何关系作用域链是在声明的时候生成,而不是调用的时候。
了解一下js的词法作用域咯,A并不会找b作用域链上的val;并且其父域是根据其声明时位置,所以上级作用域链是window
函数写在哪里,哪里就是它的作用域
而不是执行的时候的环境
你所给的 A 和 B 是兄弟关系,而不是包含关系
js中遵循词法作用域,函数的作用域链在声明时就已经确定了。
通俗一点来说,代码在执行之前,会先为当前代码中的函数先创建一个“作用域”,并将该作用域插入到当前的作用域链的顶端中,函数在执行时能够沿着这一条作用域链向上寻找自己需要的变量。
根据你的代码A和B函数在声明时就已经确定不在同一条作用域链上(不过他们的末尾,也就是window作用域是共通的)。
第一个例子中,“报错,val未定义“是因为A函数执行时遍历了整个作用域链都没有找到val
第二个例子中,A函数输出val为456是因为在A函数的作用域链中的val的值就只有在全局作用域下定义的456。
首先你是在函数B里执行函数A,函数A内找不到变量val,就去window上找,也没找到,所以就报undefined。
你理解错误A和B的作用域了,作用域链是在声明的时候就生成了。
他在 找那个变量的时候,先在本身的函数作用域里面找,如果没有,不是 在函数调用 的那块作用域里面找,而是在 函数生成(声明)的那块作用域里面找,如果还没有,再依次往上级作用域里面推,你理解的顺序错了。建议你可以看下 王福鹏 的 深入理解javascript原型和闭包系列
function也是一个作用域啊。
变量是要先定义后使用的,每个函数都是一个作用域,在函数作用域中重新定义的变量只在这个函数中可以使用,跳出函数作用域后就是使用的全局的变量了。
楼上各位大佬回答得很明确了,其实就是作用域的问题
A()和B()是两个作用域,B()里面声明的变量,A()里面肯定找不到。