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

请教一个预编译的问题

  •  
  •   kuanng · 2019-05-22 22:19:40 +08:00 · 3221 次点击
    这是一个创建于 2017 天前的主题,其中的信息可能已经有所发展或是发生改变。

    网上说预编译的最后一步几乎都是:找到函数声明,将函数名当作 AO 对象的属性,对应属性的值为函数体。

    按照这样的理解,下面的调用 bar 肯定是成功的。

    function foo() {
      bar() 
      function bar() {}
    }
    
    foo()
    

    稍微修改一下。

    function foo() {
      bar() //bar is not a function
      {
        function bar() {}
      }
    }
    
    foo()
    

    如上所示,bar 的值不是一个 function,而是 undefined。

    为什么 bar 是 undefined ?

    第 1 条附言  ·  2019-05-22 22:58:47 +08:00

    如果是作用域的问题,那么下面代码为什么运行成功

    function foo() {
      {
         function bar() {}
      }
      bar()
    }
    
    foo()
    
    11 条回复    2019-05-23 11:12:24 +08:00
    littlewing
        1
    littlewing  
       2019-05-22 22:33:22 +08:00 via iPhone
    是不是作用域的问题?
    secondwtq
        2
    secondwtq  
       2019-05-22 22:35:35 +08:00
    这跟预编译有什么关系么 ...
    kuanng
        3
    kuanng  
    OP
       2019-05-22 22:40:09 +08:00
    @secondwtq 那请教一下是什么问题呢?
    bestie
        4
    bestie  
       2019-05-22 22:52:21 +08:00
    你这是作用域的问题。。和预编译有啥关系
    kuanng
        5
    kuanng  
    OP
       2019-05-22 22:54:27 +08:00
    @littlewing 如果是作用域的问题,那么下面这段代码也一定是错的
    function foo() {
    {
    function bar() {}
    }
    bar()
    }

    foo()
    但是它却是运行成功的
    VDimos
        6
    VDimos  
       2019-05-22 23:03:25 +08:00 via Android
    脚本语言哪来编译一说
    autoxbc
        7
    autoxbc  
       2019-05-22 23:03:25 +08:00   ❤️ 1
    对于已经实现 ES6 的浏览器,在块级作用域中的函数声明是有些混乱的,具体可以看教程

    https://es6.ruanyifeng.com/#docs/let#%E5%9D%97%E7%BA%A7%E4%BD%9C%E7%94%A8%E5%9F%9F%E4%B8%8E%E5%87%BD%E6%95%B0%E5%A3%B0%E6%98%8E

    关键的部分摘录如下

    允许在块级作用域内声明函数。
    函数声明类似于 var,即会提升到全局作用域或函数作用域的头部。
    同时,函数声明还会提升到所在的块级作用域的头部。

    按照我的理解,题目中的代码,实际是按照这样解析

    function foo() {
    var bar
    bar()
    {
    bar = function () {}
    }
    }

    foo()

    原则上,为了避免歧义,应该彻底弃用函数声明,一律用函数表达式
    kuanng
        8
    kuanng  
    OP
       2019-05-22 23:35:55 +08:00
    @autoxbc 感谢
    aaniao002
        9
    aaniao002  
       2019-05-23 01:45:49 +08:00 via Android
    var bar= () =>
    KuroNekoFan
        10
    KuroNekoFan  
       2019-05-23 08:10:32 +08:00 via iPhone
    function 定义和 var 都会带来变量提升,此题终结
    redbuck
        11
    redbuck  
       2019-05-23 11:12:24 +08:00
    ES6 添加了块级作用域,所以你用{}包起来就有了一个私有的作用域.

    如果你在 ES5 环境中(IE8 以下)应该不会报错
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1027 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 20ms · UTC 21:30 · PVG 05:30 · LAX 13:30 · JFK 16:30
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.