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

为什么 js 对象里的方法不查找对象里的属性?

  •  
  •   rebeccaMyKid · 2017-06-20 10:54:29 +08:00 · 1710 次点击
    这是一个创建于 2715 天前的主题,其中的信息可能已经有所发展或是发生改变。

    对于作用域链的问题,这个代码我理解:

    var name = 23;
    function sayName(){
        return name;
    }
    console.log(sayName()); //23
    

    当前函数作用域没有name就往上找。

    但是,这个为什么不返回对象的 name 属性?

    var name = 23;
    var obj = {
        name: 666,
        getName: function(){
            return name;
        }
    };
    console.log(obj.getName()); //23
    

    加上

    return this.name; 就可以

    13 条回复    2017-06-21 07:56:56 +08:00
    jtsai
        1
    jtsai  
       2017-06-20 11:06:48 +08:00
    var name 是局部变量
    name 是全局变量 (没有加 var )

    这段代码,你在 obj 里定义的 name 跟 在 obj 外 定义的 name 都是 window.name
    jtsai
        2
    jtsai  
       2017-06-20 11:08:30 +08:00
    噢 我搞错
    mufeng
        3
    mufeng  
       2017-06-20 11:09:48 +08:00
    jtsai
        4
    jtsai  
       2017-06-20 11:12:00 +08:00
    name: 666, 不是定义变量 name,而是定义 obj 对象的属性 name 的值 = 666

    getName: function(){ return name; } 这段是访问 name 这个变量,不是范围 obj.name 这个属性
    acthtml
        5
    acthtml  
       2017-06-20 11:13:49 +08:00
    this 指向上级对象。
    var 的作用域在 function 或全局中。
    acthtml
        6
    acthtml  
       2017-06-20 11:14:25 +08:00
    @acthtml 应该这么说,this 指向运行时的上级对象。
    morethansean
        7
    morethansean  
       2017-06-20 11:16:39 +08:00   ❤️ 1
    谁给你说你调一个对象下的函数对象的属性就会被自动加到 scope chain 里的……
    DUSTINTHEWIND
        8
    DUSTINTHEWIND  
       2017-06-20 11:33:01 +08:00
    我觉得应该是这样:这里面一共两个域:1. global 2. getName
    getName 返回的 name 先在 getName 域里面查找,没找到,就到 global 域上找,找到了,于是打印 23
    但是为什么不返回 obj 的 name,这.......总觉得哪里有点奇怪
    forgcode
        9
    forgcode  
       2017-06-20 12:02:15 +08:00
    bj.getName()这个方法的执行环境在 window!
    基本判断环境
    1.是不是 new 的
    2.是不是通过 call、apply
    3.在其他上下文环境调用
    4.然后就是默认,用严格模式就 undefined 不然就全局对象
    noe132
        10
    noe132  
       2017-06-20 12:33:57 +08:00
    因为 js 的对象是动态对象。如果 obj 本来没有 name 这个属性,你的 getname 依赖的是外部的变量 name 的值

    若这个 obj 被其他地方修改,添加了个 name 属性,那么问题来了,要返回 obj.name 还是 obj 外部的变量 name 的值呢?

    如果默认会返回 obj.name,那么就算 obj.name 没有定义,它的值也是 undefined,那到底是返回外部的值还是返回 undefined 呢?

    所以 JS 中的作用域是在函数定义的时候确定的,不是函数调用的时候确定的。而且不像 Java,就算没有显示指定 this,作用域没找到相应变量时会自动找当前对象上的值,因为 Java 的对象都是固定写好的类,属性名和方法名都是写死的,不会出现上述问题。

    况且,方法在对象上必须以 obj.method()的方式调用时 this 才指向 obj,如果 var method = obj.method; method(); method()中的 this 在非严格模式下是 global 对象,严格模式下是 undefined。
    rebeccaMyKid
        11
    rebeccaMyKid  
    OP
       2017-06-20 14:34:55 +08:00
    @morethansean 嗯!
    vincedd
        12
    vincedd  
       2017-06-21 07:46:39 +08:00 via iPhone
    return this.name 等价于 return obj.name,调用问题中调用 getName 的时候,当前作用域是 getName,上一级的作用域应该是 window,这么理解对不对?
    rebeccaMyKid
        13
    rebeccaMyKid  
    OP
       2017-06-21 07:56:56 +08:00 via iPhone
    @vincedd 应该是这样的
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3005 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 14:42 · PVG 22:42 · LAX 06:42 · JFK 09:42
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.