V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
xrr2016
V2EX  ›  程序员

求教一个问题.

  •  
  •   xrr2016 ·
    xrr2016 · 2017-08-03 20:19:39 +08:00 · 2147 次点击
    这是一个创建于 2454 天前的主题,其中的信息可能已经有所发展或是发生改变。

    今天我在 javascript 高级程序设计第 7 章 上看到这样一段代码

    var name = 'window'
    var obj = {
      name: 'obj',
      getName: function () {
        return this.name
      }
    }
    
    obj.getName() // 输出 'obj'
    (obj.getName)() // 输出 'obj')
    (obj.getName = obj.getName)()  // 输出 'window'
    

    我理解为

    (obj.getName = obj.getName)() 
    // 等同于
    (function() { return this.name })()
    

    不知这样想是否正确?

    然后我又用 let 和 const 试了一下, 结果都输出空字符串, 说以想问下原因何在?

    14 条回复    2017-08-04 12:35:41 +08:00
    suikator
        1
    suikator  
       2017-08-03 21:20:08 +08:00
    Variable is assigned to itself
    This inspection reports any assignments of the form x = x in JavaScript content. These are pointless, and usually indicate programmer error
    geelaw
        2
    geelaw  
       2017-08-03 21:27:27 +08:00 via iPhone
    我先提示一下 obj 是 const 的意思是 obj 不能改变引用了哪个对象,并不是对象本身不可改变,在这个例子里 const 不 const 不会有区别
    suikator
        3
    suikator  
       2017-08-03 21:35:23 +08:00
    在 var name = 'window' 下面 console 一下 this 吧 看看里面有没有 name,我估计没有

    研究这些操蛋的东西真的有前途吗 - -!
    xrr2016
        4
    xrr2016  
    OP
       2017-08-03 21:50:43 +08:00
    @suikator 肯定有啊,var name = 'window' 的时候 this 就是全局对象.
    哈哈. 我也只是今天在看书的时候看到的,也算不上研究吧。
    xrr2016
        5
    xrr2016  
    OP
       2017-08-03 21:57:27 +08:00
    @geelaw 不太能理解您的意思,按理说 `(obj.getName = obj.getName)()` 这句执行的时候,运行的都是 `return this.name` 啊, 为什么 `var` 声明可以输出 'window', 而 `let` 和 `const` 声明不行呢?
    suikator
        6
    suikator  
       2017-08-03 22:14:19 +08:00
    @xrr2016
    区分 全局中的 this 函数中的 this 构造函数中的 this 以及 this 的指向
    chrome 浏览器环境 全局中的 this === windows
    此时 (obj.getName = obj.getName)() 输出 'window' 没毛病
    其他环境我不清楚 你自己打印吧 我也不是很熟练 js
    fulvaz
        7
    fulvaz  
       2017-08-03 22:30:58 +08:00
    楼主的问题好有意思,我测试发现了几个问题

    问题 1
    ----
    楼主的第一段代码就跑不通吧?

    ```
    (obj.getName)()
    ````
    会产生 TypeError

    问题 2
    ---
    楼主在 console 中分段执行的代码, 如果连在一起执行的话

    ```
    let name = 'window2'
    let obj = {
    name: 'obj',
    getName: function() {
    return this.name
    }
    }
    (obj.getName = obj.getName)()
    ```

    Uncaught ReferenceError: obj is not defined


    值得研究一番
    fulvaz
        8
    fulvaz  
       2017-08-03 22:33:21 +08:00
    @fulvaz

    分号的问题,分号的问题。。。下次弄明白了再扔上来
    xrr2016
        9
    xrr2016  
    OP
       2017-08-03 23:10:35 +08:00
    @fulvaz 跑的通啊, 你怎么跑不通的...
    RLib
        10
    RLib  
       2017-08-03 23:28:39 +08:00
    @xrr2016 因为 `var` 和 `let const` 的作用域不一样, var 声明的作用域是全局的, 用 this 得到 window, 但是 let 是块级作用域(并且不是全局作用域), let 声明的全局变量也不具有全局对象的属性, 这时候 this.name 就是 undefined
    fulvaz
        11
    fulvaz  
       2017-08-04 00:51:06 +08:00
    @RLib 我觉得与作用域无关啊

    楼主的代码中有个小坑,就是 window.name 是存在的, 值为""

    楼主迷惑的话可以尝试下这样的代码

    代码 1
    ----

    ```
    window.name; // -> ""
    var name = 123;
    window.name; // -> 123
    ```

    var 竟然能修改全局变量的值

    代码 2
    ---
    ```
    window.name; // ""
    let name = 123;
    window.name; // ""
    ````

    let 不会修改全局变量

    -------------------------

    总结而言就是...js 的历史遗留问题,var 定义的变量到底保存在哪里。
    xrr2016
        12
    xrr2016  
    OP
       2017-08-04 09:05:21 +08:00
    @fulvaz 这不是历史遗留问题吧, 代码运行的时候本来就有一个全局对象存储变量啊
    RLib
        13
    RLib  
       2017-08-04 10:30:52 +08:00   ❤️ 1
    @fulvaz 相对来说 let 和 const 是新玩法, var 才是历史产物, 提出 let 就是为了解决`var 任何地方都是全局作用域`而产生的 bug。
    window.name 是本来存在, 但因为在 LZ 的代码里并没体现, 所以我说是 undefined, 但这是全局变量, 而声明的是 let, 不等于全局, let 不会影响全局变量尽管它在全局块, 此外, 既然 let 不能修改全局变量, 不也从另一方面表明 let 的变量不在全局作用域里。所以说来说去就是个简单的作用域问题
    xrr2016
        14
    xrr2016  
    OP
       2017-08-04 12:35:41 +08:00
    @RLib 这样说我就明白了, `window.name` 本来就是空字符串,多谢。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3451 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 11:30 · PVG 19:30 · LAX 04:30 · JFK 07:30
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.