js 作用域问题? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
jtsai
V2EX    问与答

js 作用域问题?

  •  
  •   jtsai 2017-06-21 08:50:55 +08:00 2459 次点击
    这是一个创建于 3037 天前的主题,其中的信息可能已经有所发展或是发生改变。
    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     Solana     3213 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 48ms UTC 11:48 PVG 19:48 LAX 04:48 JFK 07:48
    Do have faith in what you're doing.
    ubao 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