V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
victory
V2EX  ›  JavaScript

看书看迷糊了 求解答

  •  1
     
  •   victory · 2022-04-06 17:08:48 +08:00 · 3681 次点击
    这是一个创建于 965 天前的主题,其中的信息可能已经有所发展或是发生改变。

    在看《 JavaScript 高级程序设计(第 4 版)》第 3 章第 3 节变量 看迷糊了

    1. var 声明作用域 关键的问题在于,使用 var 操作符定义的变量会成为包含它的函数的局部变量。比如,使用 var 在一个函数内部定义一个变量,就意味着该变量将在函数退出时被销毁:
    function test() { 
     var message = "hi"; // 局部变量
    } 
    test(); 
    console.log(message); // 出错!
    }
    

    下面这个代码为什么没有报错啊

    if (true) { 
     var name = 'Matt'; 
     console.log(name); // Matt 
    } 
    console.log(name); // Matt 
    

    这个 name 变量 怎么变成全局变量了

    31 条回复    2022-04-08 12:07:48 +08:00
    Puteulanus
        1
    Puteulanus  
       2022-04-06 17:10:49 +08:00   ❤️ 1
    “使用 var 操作符定义的变量会成为包含它的函数的局部变量”
    因为 if 的块不是函数呀
    kop1989smurf
        2
    kop1989smurf  
       2022-04-06 17:12:14 +08:00
    https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/var
    var 语句 用于声明一个函数范围或全局范围的变量,并可将其初始化为一个值(可选)。
    victory
        3
    victory  
    OP
       2022-04-06 17:14:39 +08:00
    @Puteulanus if()不是函数 if 的块不是函数 这两个是什么意思 我初学者没有编程经验 可以详细说一下吗
    noe132
        4
    noe132  
       2022-04-06 17:15:22 +08:00
    块作用域 !== 函数作用域。
    var 没有块作用域
    let/const 有块作用域

    { let myname = 'Matt'; console.log(myname); }
    console.log(myname); // Uncaught ReferenceError: myname is not defined

    另外 name 在浏览器中是个全局变量。
    einq7
        5
    einq7  
       2022-04-06 17:28:03 +08:00
    @victory #3 var 声明的变量没有块级作用域,if 的大括号和其所包含的是个语句块,所以在里面用 var 声明的变量,可以在语句块外部访问到
    victory
        6
    victory  
    OP
       2022-04-06 17:31:16 +08:00
    @einq7 感觉 JavaScript 好多坑啊 有时候是局部变量,有时候是全局变量
    victory
        7
    victory  
    OP
       2022-04-06 17:32:43 +08:00
    还有一个问题 var 都是在什么情况下会变成全局变量
    stimw
        8
    stimw  
       2022-04-06 17:35:55 +08:00 via iPhone
    var 是老式的用法,有很多坑,现代 js 中应该避免使用 var 。var 是不受块( block )作用域限制的。block 本身也是现代 js 才引入的
    stimw
        9
    stimw  
       2022-04-06 17:37:08 +08:00
    这里讲的比较详细
    https://zh.javascript.info/var
    shintendo
        10
    shintendo  
       2022-04-06 17:48:36 +08:00
    你为什么觉得,在你的例子里 name 是个全局变量
    nekochyan
        11
    nekochyan  
       2022-04-06 17:50:05 +08:00
    我怎么感觉你连什么是函数都没搞明白
    victory
        12
    victory  
    OP
       2022-04-06 17:56:51 +08:00
    @shintendo 可以在函数外使用的变量不叫全局变量叫什么
    shintendo
        13
    shintendo  
       2022-04-06 17:59:39 +08:00
    @victory 那么 name 在哪个函数外使用了?
    IceBay
        14
    IceBay  
       2022-04-06 18:24:40 +08:00
    Chell
        15
    Chell  
       2022-04-06 18:25:12 +08:00
    函数产生的是 function scope ,if 语句产生的是 block scope 。JS 没有实现 block scope ,但用 let 替代 var 可以产生你期待的效果。
    darkkylin
        16
    darkkylin  
       2022-04-06 18:36:27 +08:00
    楼主是不是受其他语言的影响了。建议看 ES6 的语法规则,按照新的规则来写。这种迷惑是历史原因了,语言设计导致,不用太纠结。
    ES6 以前 js 没有实现 block scope ,只有 function scope 和 global scope 。
    if 语句只是 block scope 。
    zhaol
        17
    zhaol  
       2022-04-06 18:36:44 +08:00
    if 不是函数啊
    xQmQ
        18
    xQmQ  
       2022-04-06 19:46:52 +08:00
    我主要是做后端搞 c++ 的,这几天刚学了一点 JavaScript ,搞毕设的前端,也想问一下

    if (true) {
    var name = 'Matt';
    console.log(name); // Matt
    }
    console.log(name); // Matt

    name 为啥能用来打印呢? f() 判断式不能确定一定能进入(只是这里的恒定为 true ,保证了一定能进入),name 居然还定义成功了,我不能理解这种玩法
    Moeyua
        19
    Moeyua  
       2022-04-06 20:27:44 +08:00 via iPhone
    @xQmQ var 的变量声明会被提前到最开始,但此时不会被赋值,也就是如果 if 判断为 false ,这里打印的结果就会是 undefined
    xQmQ
        20
    xQmQ  
       2022-04-06 21:18:59 +08:00
    @Moeyua 试了一下,确实如此。但是之前先测试了 if(true) 的,输出两次;然后测试了 if(false) 的,也输出了两次。考虑了一下,应该是浏览器控制台记录了第一次时的值,导致第二次的 name 已经赋值了
    mascteen
        21
    mascteen  
       2022-04-06 21:22:39 +08:00 via Android
    换一本书看吧,这本书不符合新手,推荐权威指南
    jadehare
        22
    jadehare  
       2022-04-06 21:30:00 +08:00
    es6 建议使用 let 和 const ,不用管啥 var 啥作用域了,你叫一个开发很久习惯使用 let 的人来也得反应一会,这不是正常开发的思路。
    Leviathann
        23
    Leviathann  
       2022-04-06 23:00:45 +08:00
    es6 都快 10 年了
    demo06
        24
    demo06  
       2022-04-07 09:00:43 +08:00
    @xQmQ if 不是函数语句块,会导致变量作用域提升,所以你在 if(boolean){var xx=x;}所以你能打印成功
    demo06
        25
    demo06  
       2022-04-07 09:01:50 +08:00
    @xQmQ if 不是函数语句块,会导致变量作用域提升,所以你在 if(boolean){var xx=x;}时,var 变量会被提升到文件头部,所以你能打印成功
    demo06
        26
    demo06  
       2022-04-07 09:26:23 +08:00
    @xQmQ 不对我描述的有问题,应该是 javascript 没有块级作用域,变量会被提升
    xQmQ
        27
    xQmQ  
       2022-04-07 09:55:24 +08:00
    @demo06 var 是没有块级作用域的,所以以下代码在浏览器控制台初次打印时提示 userName 是 undefined ,打印结果是 2.undefined ( userName 被提升了)

    if(false){
    var userName = 'test';
    console.log('1.'+userName);
    }
    console.log('2.'+userName);

    但是如果执行一次 if(true),再执行 if(false) 会打印成功;我这里猜测是因为解释器的原因,userName 被记录了,所以可以打印成功

    你提到『 JavaScript 没有块级作用域』,var 没有,let 应该是有的
    demo06
        28
    demo06  
       2022-04-07 11:07:43 +08:00
    @xQmQ 在浏览器和 vs 里分别执行试了下,浏览器会记录,vs 还是 undefind
    xQmQ
        29
    xQmQ  
       2022-04-07 12:22:47 +08:00
    @demo06 浏览器估计是交互模式,带记录,vs 估计解释器直接执行文件了
    ljpCN
        30
    ljpCN  
       2022-04-07 14:31:50 +08:00
    关于块作用域楼上解释得差不多了,我给楼主一个建议:别用 var 。用 const 和 let 。
    dany813
        31
    dany813  
       2022-04-08 12:07:48 +08:00
    var 弃用吧,js 各种垃圾语法太多了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5969 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 02:02 · PVG 10:02 · LAX 18:02 · JFK 21:02
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.