Javascript 的代码与 babel/es6 的代码执行时的一些问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a Javascript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
Javascript 权威指南第 5 版
Closure: The Definitive Guide
Macya
V2EX    Javascript

Javascript 的代码与 babel/es6 的代码执行时的一些问题

  •  
  •   Macya 2016-10-15 21:28:55 +08:00 3072 次点击
    这是一个创建于 3287 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近在看 es6 入门教程,在函数的扩展那一章有这样一个例子:

    var x = 1; function foo (x, y = function(){x=1;}){ var x = 3; y(); console.log(x); // 3 选择 Javascript 选项 (书中给出的答案是这个) // 1 选择 es6/babel 选项 } foo(); 

    这个例子我是在 jsbin 上测试的,

    jsbin 的 js 代码填写处出可以选择 Javascript 或者 es6/babel ,

    我选择 Javascript 选项时上面的例子会输出打印 3 ,选择 es6/babel 选项时打印 1

    我想知道为什么这两个选项在处理 js 代码时又怎样的区别?

    假设以 Javascript 那个选项的为标准 这个例子为什么最后会打印出 3 ?

    我个人的理解是(有错误希望能指出):赋予 y 变量的那个匿名函数在声明(定义?)时 foo 函数的作用域还未形成,也就是说在 foo 函数执行前,创建 foo 函数的执行上下文的时候,先完成 foo 函数中的参数声明,第一个参数是 X ,此时 x 赋值为 undefined ,第二个参数是 y , y 赋值为一个匿名函数,并且这个匿名函数在这个时候被声明(定义?),此时这个匿名函数保存了自己的作用域链,这个作用域链包含它自身声明的变量及 foo 函数参数中的 x ,还有 window 的活动对象。完成了参数变量的声明和赋值后,接下来是函数声明,然后时变量声明,这时新声明的 x 将参数声明中的 x 覆盖了,所以最后打印了 3 。

    6 条回复    2016-10-16 10:23:21 +08:00
    crs0910
        1
    crs0910  
       2016-10-15 22:07:53 +08:00
    babel 转换有问题吧,默认值写匿名函数,转到 foo 里面少了 var ,覆盖了 foo 里面的 x
    crs0910
        2
    crs0910  
       2016-10-15 22:11:08 +08:00
    事实上应该转成

    ```
    var x = 1
    function foo(x) {
    var y = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () {
    var x = 1
    }
    var x = 3
    y()
    console.log(x)
    }
    foo()
    ```
    crs0910
        3
    crs0910  
       2016-10-15 22:50:56 +08:00
    看了一下, 这里的 foo 里面的 x 和 参数 y 默认值里面的 x 都是指的参数 x (也就是 undefined), 匿名函数里面对 x 赋值操作改变的是参数 x , foo 函数里面又声明了 var x 并赋值,这里的 x 已经不是参数 x 了(去掉 var 的话就还是参数 x ), 所以执行 y 并不会改变 foo 里面的 x
    crs0910
        4
    crs0910  
       2016-10-15 22:52:26 +08:00
    babel 转换的时候把参数里面的匿名函数扔 foo 里面去赋值了, x 就覆盖了
    Macya
        5
    Macya  
    OP
       2016-10-16 00:51:26 +08:00
    @crs0910 事实上,在 es6 入门教程中,作者也是提过:函数中新声明的变量如果与参数中的变量同名,这两个变量并不相同,也就是说函数中新声明的 x 与参数变量中的 x 并不是同一个 x 。但是对于这一点我不明白的是在新声明 x 之后, y 函数任然可以操作之前的参数变量 x ,难道可以理解为在 foo 函数作用域中同时存在一个参数变量 x 和一个变量声明 x ?而 y 函数中的作用域链只保存了参数变量 x ,新声明的 x 无论怎么操作都与 y 函数作用域链中的 x 互不干扰?

    又或者说,参数变量 y 在赋值匿名函数时产生了闭包,导致它保存的 x 不受外界干扰?但是这样一来,假设 foo 函数中没有新声明 x ,而是直接调用 x 进行赋值操作,(将"var x = 3" 改成 "x=3"),闭包的说法也就不妥当了。
    meszyouh
        6
    meszyouh  
       2016-10-16 10:23:21 +08:00 via Android
    https://developer.mozilla.org/zh-CN/docs/Web/Javascript/Reference/Functions/Default_parameters
    这里可能对你有帮助,前置参数对于后面参数可见的。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1239 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 82ms UTC 17:21 PVG 01:21 LAX 10:21 JFK 13:21
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86