V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
jtsai
V2EX  ›  问与答

js 作用域问题?

  •  
  •   jtsai · 2017-06-21 08:50:55 +08:00 · 1991 次点击
    这是一个创建于 2508 天前的主题,其中的信息可能已经有所发展或是发生改变。
    window.name = 'abc';
    window.getName = function () {
    	alert(name)
    }
    window.getName() // abc
    
    var obj = {}
    obj.name = '123'
    obj.getName = function () {
    	alert(name)
    }
    obj.getName() // abc
    

    怪吗?

    25 条回复    2017-06-22 09:59:44 +08:00
    deleteDB
        1
    deleteDB  
       2017-06-21 08:57:16 +08:00
    要写 alert(this.name)
    Fishdrowned
        2
    Fishdrowned  
       2017-06-21 08:57:32 +08:00 via Android
    不怡啊,这根本不是作用域,少年你混淆概念了。
    Rice
        3
    Rice  
       2017-06-21 08:57:58 +08:00
    这样你就觉得怪了?

    ```
    window.name = 'abc';
    var obj = {}
    obj.name = '123'
    obj.getName = function () {
    alert(this.name)
    }
    obj.getName() // 123
    var a = obj.getName;
    a();
    ```

    那这样呢?
    pandasjw
        4
    pandasjw  
       2017-06-21 08:58:54 +08:00 via Android
    这是全局变量的问题吧。。。
    jtsai
        5
    jtsai  
    OP
       2017-06-21 09:01:42 +08:00
    @Rice 你这个是 this 作用域的问题。可以被理解,我那个是变量加载的问题,为什么变量是这样加载的
    Rice
        6
    Rice  
       2017-06-21 09:04:25 +08:00
    @jtsai #5 可能是因为 js 没有类的概念吧。
    Rice
        7
    Rice  
       2017-06-21 09:10:56 +08:00   ❤️ 1
    @jtsai #5
    你这样想吧,js 不是现在这样设计
    而是对象方法调用的时候,先查找有没有当前对象的 name 值,然后没有再向上查找,这样会发生什么后果。
    这样的后果就是,如果这个对象一开始就没有 name 值,调用的时候就是全局变量 name
    结果被人后来修改了,加上 name,调用就是对象的属性 name。
    R18
        8
    R18  
       2017-06-21 09:16:12 +08:00
    你的意思是 应该 alert 123 吗?但是你的 123 是赋值给了一个对象的属性 对象属性的调用是 obj.name 你直接使用 name 是会逐层寻找这个变量 最后就找到了全局中的 name
    jin5354
        9
    jin5354  
       2017-06-21 09:18:04 +08:00
    在 ES6 前只有函数作用域和全局作用域,不要靠惯性和臆测写代码
    morethansean
        10
    morethansean  
       2017-06-21 09:19:53 +08:00
    连续两天见到同一个问题了,到底是谁教你们的调对象下面的函数,对象的属性就会被自动加到 scope chain 里啊?
    secondwtq
        11
    secondwtq  
       2017-06-21 09:23:15 +08:00 via Android
    @jtsai 你用 Python 写 method 访问实例变量不也是要写 self
    sliwey
        12
    sliwey  
       2017-06-21 09:26:08 +08:00
    不怪
    jtsai
        13
    jtsai  
    OP
       2017-06-21 09:27:43 +08:00
    @Rice
    @R18
    @jin5354
    @morethansean
    @secondwtq

    @Rice
    ```
    name = 'abc'

    class obj():
    def __init__(self):
    self.name = '123'

    def getName(self):
    print(name)

    obj().getName() # abc
    ```

    其实只是 js 的表达看起来有点怪 这样就很正常了。一直都是这样的。
    Rice
        14
    Rice  
       2017-06-21 09:31:29 +08:00
    @jtsai #13 我刚才突然想到动态语言是不是都这样,正打算看 Python 里的类是不是也是这样。
    luchenqun
        15
    luchenqun  
       2017-06-21 09:34:58 +08:00
    http://t.cn/Ro5N24k
    此问题到此终结!
    vincedd
        16
    vincedd  
       2017-06-21 09:50:46 +08:00 via iPhone
    @luchenqun 哈哈哈哈哈
    Rice
        17
    Rice  
       2017-06-21 09:52:11 +08:00
    @luchenqun #15 我看你是连我们在讨论什么都没看吧。
    jtsai
        18
    jtsai  
    OP
       2017-06-21 09:53:22 +08:00
    @luchenqun 老板,我这题跟 this 没有半毛钱关系
    BlackLynx
        19
    BlackLynx  
       2017-06-21 10:07:48 +08:00
    九楼十楼正解
    DUSTINTHEWIND
        20
    DUSTINTHEWIND  
       2017-06-21 10:52:53 +08:00
    这个昨天一个帖子的问题一模一样
    xxfan
        21
    xxfan  
       2017-06-21 11:27:43 +08:00
    少年可以看高程 4.2 节来理解一下执行环境和作用域链.
    我的理解是,作用域链,0 位是当前执行环境,也就是当前的 function(){} 花括号内的,显然 getName 这个函数内没有定义 name,找不到.
    然后再后一位,就是 window 这个执行环境了,window 中可以找到 name.返回 abc.

    obj 并不是 getName 的执行环境,不在作用域链内,它只是"调用环境",也就是调用这个函数的对象而已.(所以 this 的话指向 obj,而作用域不包含它)
    sunjourney
        22
    sunjourney  
       2017-06-21 13:54:47 +08:00
    为什么怪,有什么其它语言 obj.getName() 会是 123 ?不是 123 我才要惊了
    jtsai
        23
    jtsai  
    OP
       2017-06-21 14:10:36 +08:00
    @sunjourney
    我感觉有点怪是因为
    window instanceof Object // ture
    obj instanceof Object // ture
    window.toString === obj.toString // true

    咋一看差不多的
    xiaojunjor
        24
    xiaojunjor  
       2017-06-21 14:56:53 +08:00
    @luchenqun 哈哈哈哈哈哈,这个笑死我了
    Tokin
        25
    Tokin  
       2017-06-22 09:59:44 +08:00
    @sunjourney JavaScript 中的任何一个全局函数或变量都是 window 的属性。
    在 obj.getName 里调用的 name 是全局的 name 啊,如果要掉 obj 的 name 需要 this.name 或者 obj.name 不是吗?好奇。。。
    式作用域的问题?调错了的可能性大吧。。。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2394 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 33ms · UTC 14:54 · PVG 22:54 · LAX 07:54 · JFK 10:54
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.