为什么这种写法是错的

今天突然想到个问题,如果在方法中访问一个将来会存在的变量,能不能成功,如下:

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不是非编译的么。

阅读 4.8k
13 个回答

B和A在作用域链上是平级关系,并不会因为B调用了A就变成A的父作用域,除非A在B里面声明


function B() {
    var val = 123;
    function A() {
        console.log(val);
    }
    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也是一个作用域啊。

var val = 456;
function A() {
    console.log(val);
}

function B() {
    val = 123;
    A();
}
B();//123

变量是要先定义后使用的,每个函数都是一个作用域,在函数作用域中重新定义的变量只在这个函数中可以使用,跳出函数作用域后就是使用的全局的变量了。

楼上各位大佬回答得很明确了,其实就是作用域的问题
A()和B()是两个作用域,B()里面声明的变量,A()里面肯定找不到。

新手上路,请多包涵

嘿嘿 你可以这样

function A() {
    console.log(val);
}

function B() {
    // 不加var默认声明全局变量
    val = 123;
    A();
}
B();


新手上路,请多包涵
function A(val) {
    console.log(val);
}

function B() {
    var val = 123;
    A(val);
}
B();

你这样试试

谢邀!
根据函数提升机制,先编译A,编译A的时候因为找不到val,就报错了(val is not defined)
如果改为

function A(val) {
    console.log(val);
}

function B() {
    var val = 123;
    A(val);
}
B();

则编译A的时候不会报错,B也不会报错,编译没报错后面就可以运行了。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题