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 · 3288 次点击
    这是一个创建于 1457 天前的主题,其中的信息可能已经有所发展或是发生改变。
    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()
    YuxiangLuo
        5
    YuxiangLuo  
       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
    你这个是运算符优先级问题,不是作用域问题。
    wunonglin
        8
    wunonglin  
       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 属性,所以会返回空字符串
    zhengjian
        27
    zhengjian  
       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   ·   我们的愿景   ·   实用小工具   ·   3309 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 37ms · UTC 00:05 · PVG 08:05 · LAX 17:05 · JFK 20:05
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.