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

问一个 ES6 作用域的问题

  •  
  •   jingcoco 2020-04-01 15:13:49 +08:00 3823 次点击
    这是一个创建于 2024 天前的主题,其中的信息可能已经有所发展或是发生改变。
    var value = 1; var foo = { value: 2, bar: function () { return this.value; } } //示例 1 console.log(foo.bar()); //示例 2 console.log((foo.bar)()); 

    为什么这两个结果一样.老感觉第二个结果是 value=1 这个

    第 1 条附言    2020-04-01 19:05:32 +08:00
    感谢楼下各位回复,自己想感觉容易钻牛角尖. 感悟就是 平时工作基本不会这么写,但是一涉及到理论(面试 )感觉是不是还是必要去系统看看.....
    35 条回复    2020-04-02 11:14:06 +08:00
    TabGre
        1
    TabGre  
       2020-04-01 15:20:03 +08:00
    1. this 的隐式绑定
    2. this 的隐式绑定回退为默认绑定,非严格模式下 this 为 global(window)
    salamanderMH
        2
    salamanderMH  
       2020-04-01 15:21:56 +08:00
    foo.bar 这个属性就是一个函数,这两种写法一样的,this 还是指向 foo 的。
    TabGre
        3
    TabGre  
       2020-04-01 15:22:57 +08:00
    @TabGre LOL,忽略我的回答,我也没有完全搞明白。dog
    daquandiao2
        4
    daquandiao2  
       2020-04-01 15:23:57 +08:00
    ff = foo.bar

    ff()
    1KN6sAqR0a57no6s
        5
    1KN6sAqR0a57no6s  
       2020-04-01 15:25:39 +08:00
    let x = foo.bar;
    console.log(x());
    这样就是 1

    可能是因为 foo.bar 与(foo.bar)是同一个 reference,而 x 是复制的 reference
    TabGre
        6
    TabGre  
       2020-04-01 15:28:25 +08:00
    @daquandiao2 这样是不是就打印为 1 了呢?
    amaranthf
        7
    amaranthf  
       2020-04-01 15:29:09 +08:00
    你这个是运算符优先级问题,不是作用域问题。
    shakaraka
        8
    shakaraka  
    PRO
       2020-04-01 15:41:43 +08:00
    你把
    bar: function () {
    return this.value;
    }
    换成
    bar: () => {
    return this.value;
    }
    有惊喜
    jingcoco
        9
    jingcoco  
    OP
       2020-04-01 15:44:18 +08:00
    刚才搜索了一下 ,又晕了...
    ```
    (false|| foo.bar)()

    ```
    这样结果就是 1 了.....
    jingcoco
        10
    jingcoco  
    OP
       2020-04-01 15:45:21 +08:00
    @wunonglin 你这个我知道为什么, 箭头函数的作用域是执行环境的.
    iNaru
        11
    iNaru  
       2020-04-01 15:52:56 +08:00   1
    @jingcoco 实例 2 中括号中的(foo.bar)返回的是引用,(false|| foo.bar)的则是或运算的结果
    weikexin
        12
    weikexin  
       2020-04-01 16:02:44 +08:00   5


    max21
        13
    max21  
       2020-04-01 16:06:30 +08:00   1
    @jingcoco false|| foo.bar 的运算结果就是 function () {return this.value;},然后执行这个函数,this 指向什么对象是再函数被调用时才确定的,这里没有使用 foo.bar 调用,所以 this 指向全局对象
    ming61177
        14
    ming61177  
       2020-04-01 16:14:56 +08:00
    看不出跟 ES6 有什么关系
    kuanng
        15
    kuanng  
       2020-04-01 16:22:31 +08:00
    有点意思。我的第一直觉也是 value=1
    vivipure
        16
    vivipure  
       2020-04-01 16:37:18 +08:00   1
    和作用域没关系,主要是 Reference 没变
    TabGre
        17
    TabGre  
       2020-04-01 16:40:06 +08:00
    箭头函数的 this 不是调用确定,而是 lexical 确定的把
    DowneyLam
        18
    DowneyLam  
       2020-04-01 16:56:25 +08:00   2
    跟 Reference 有关 你可以看看这篇文章 https://github.com/mqyqingfeng/Blog/issues/7
    ironMan1995
        19
    ironMan1995  
       2020-04-01 17:09:33 +08:00
    你就和(function() {})() (function(){}())有什麽。你例都是作 foo 象的方法用的 this 指向 foo,想要 this 指向全局的 value, foo.bar 值一全局量然後行。var bar = foo.bar; bar(); //1 或者使用箭函
    Hoshinokozo
        20
    Hoshinokozo  
       2020-04-01 17:10:22 +08:00
    结果一样不是正常的吗?这两种写法都是一个意思,结果都是调用 bar 函数,没搞懂疑惑的点在哪
    morethansean
        21
    morethansean  
       2020-04-01 17:19:45 +08:00
    @Hoshinokozo #20
    我感觉楼主说得够清楚了吧,主要还是没弄清楚 `(1, foo.bar)()` 和 `(foo.bar)()` 的区别。楼下的解释也蛮好的。
    Hoshinokozo
        22
    Hoshinokozo  
       2020-04-01 17:28:58 +08:00
    @morethansean 额,还是没看懂。。。盲猜楼主是没搞懂括号的作用吗?(foo.bar)()和(foo.bar())效果是一样的,JS 里括号的作用无非就是调用函数和提升优先级,并且将括号内的内容作为表达式解析,两种情况最终都是调用 bar 函数,作为 foo 的成员函数,this 自然指向 foo 了。
    onfuns
        23
    onfuns  
       2020-04-01 17:37:53 +08:00   2
    简单理解,谁调用则 this 就指向谁,console.log((foo.bar)())这里的(foo.bar)是对 foo.bar 没有计算过,也就是这个()其实是无效的等同于 foo.bar
    otakustay
        24
    otakustay  
       2020-04-01 18:37:42 +08:00
    和 ES6 没关系,()运算符里面只有一个东西的时候,相当于不存在
    jingcoco
        25
    jingcoco  
    OP
       2020-04-01 19:17:57 +08:00
    @wunonglin @TabGre 嗯,我说错了.重新说一下
    ```
    const obj = {
    name: 'Jerry',
    greet: ()=>( {
    console.log(this.name)
    })
    }
    obj.greet.call(obj) // 箭头函数的话因为没有 this 所以 call 调用无用
    ```
    cxe2v
        26
    cxe2v  
       2020-04-01 19:46:57 +08:00
    @jingcoco 箭头函数的 this 永远指向定义这个函数时它的外部环境的 this 指向的对象且不能再背更改,你这里写的 this 指向了 window,window 没有 name 属性,所以会返回空字符串
    mmnsghgn
        27
    mmnsghgn  
       2020-04-01 19:47:54 +08:00
    @weikexin 第三问应该是 Javascript 的语句是有返回值的,在 Console 里执行语句返回的 undefined 或其他 就是语句的返回值。赋值表达式的返回值就是赋给的值。

    (foo.bar = foo.bar)()

    相当于

    var bar = (foo.bar = foo.bar)
    bar()

    也就相当于

    var bar = foo.bar
    bar()

    this 指向 window


    (foo.bar = foo.bar)() -> 10
    之后,再
    foo.bar() -> 20
    TabGre
        28
    TabGre  
       2020-04-01 20:40:42 +08:00 via iPhone   1
    @jingcoco 箭头不是没有 this,箭头函数就绑定了词法时的 this,本来是 this 是调用时决定,箭头函数在词法时就决定了
    hyy1995
        29
    hyy1995  
       2020-04-01 20:54:56 +08:00
    这种题…一般来说,都是自己编个想法来骗自己…
    loading
        30
    loading  
       2020-04-01 21:23:44 +08:00 via Android
    es6 居然会看到 var 。
    jingcoco
        31
    jingcoco  
    OP
       2020-04-02 04:49:00 +08:00 via Android
    @TabGre 你说的有道理吧。。。。但是没看懂。。。从你的用词感觉是从逻辑的层次或是编译器的角度上去讲的?
    TabGre
        32
    TabGre  
       2020-04-02 06:20:34 +08:00 via iPhone
    @jingcoco 推荐看 You don’t know JS yet
    rodjl
        33
    rodjl  
       2020-04-02 08:27:02 +08:00   1
    zhzbql
        34
    zhzbql  
       2020-04-02 10:55:05 +08:00   1
    关键词 Reference , Reference.base ; GetValue; [[call]], thisArgument; [[ThisMode]]
    ssshooter
        35
    ssshooter  
       2020-04-02 11:14:06 +08:00
    @Hoshinokozo 这样理解确实可以
    括号只用于改变优先级没有其他任何功能,至于(false|| foo.bar)()又是 1 是`||`的锅
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2364 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 35ms UTC 15:55 PVG 23:55 LAX 08:55 JFK 11:55
    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