javascript - 为什么这种写法是错的
ringa_lee
ringa_lee 2017-04-11 11:45:59
[JavaScript讨论组]

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

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

ringa_lee
ringa_lee

ringa_lee

全部回复(13)
ringa_lee

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


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

你下面那段示例代码中的两个val是完全不同的两个变量,没有任何关系

PHPz

作用域链是在声明的时候生成,而不是调用的时候。

PHP中文网

了解一下js的词法作用域咯,A并不会找b作用域链上的val;并且其父域是根据其声明时位置,所以上级作用域链是window

PHPz

函数写在哪里,哪里就是它的作用域
而不是执行的时候的环境
你所给的 A 和 B 是兄弟关系,而不是包含关系

天蓬老师

js中遵循词法作用域,函数的作用域链在声明时就已经确定了。
通俗一点来说,代码在执行之前,会先为当前代码中的函数先创建一个“作用域”,并将该作用域插入到当前的作用域链的顶端中,函数在执行时能够沿着这一条作用域链向上寻找自己需要的变量。
根据你的代码A和B函数在声明时就已经确定不在同一条作用域链上(不过他们的末尾,也就是window作用域是共通的)。
第一个例子中,“报错,val未定义“是因为A函数执行时遍历了整个作用域链都没有找到val
第二个例子中,A函数输出val为456是因为在A函数的作用域链中的val的值就只有在全局作用域下定义的456。

ringa_lee

首先你是在函数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()里面肯定找不到。

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号