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

[javacript 的 this 指向问题, 高手请进]

  •  
  •   Angela2022 · 70 天前 · 2802 次点击
    这是一个创建于 70 天前的主题,其中的信息可能已经有所发展或是发生改变。
    name = "哈哈"
    const pet1 = {
    name: 'Fluffy',
    getName1: () => this.name
    };
    console.log(pet1.getName1()); //哈哈

    function pet(name) {
    this.name = name;
    this.getName1 = () => this.name;
    }
    const cat = new pet('Fluffy');
    console.log(cat.getName1()); //Fluffy

    请问: 上面两个 console.log 都是打印相同的箭头函数, 为啥上面一个打印"哈哈", 下面一个打印 Fluffy ? 谢谢
    20 条回复    2022-11-21 13:51:07 +08:00
    looking0truth
        1
    looking0truth  
       70 天前   ❤️ 2
    () => 的上下文在声明时所在的函数中
    下面的 this 是 pet ,上面的是 global
    isolcat
        2
    isolcat  
       70 天前
    这里的 this 指向要根据你调用的环境来决定,第一个 pet1.getName1()就是指向的 global ,第二个 cat.getName1()在声明了参数'Fluffy'的情况下自然也就会指向所声明的函数
    你可以在 MDN 里搜索 this ,讲解的很详细
    anc95
        3
    anc95  
       70 天前   ❤️ 2
    一楼说的对,二楼说了和没说一样
    sweetcola
        4
    sweetcola  
       70 天前
    上面的 getName1 相当于只是一个函数变量,指向的是当前 context 的 this
    下面的 getName1 在函数中,new 之后就相当于在一个闭包里,context 不会随你在哪里调用而改变
    hahamy
        5
    hahamy  
       70 天前
    箭头函数的 this 和调用无关,定义的位置在哪,this 就指向哪
    我简单粗暴的理解是,看结束的分号 ; 在哪,this 就指向分号位置的对象
    weiwoxinyou
        6
    weiwoxinyou  
       70 天前
    ()=>{}中的 this 自动指向上一层
    rabbbit
        7
    rabbbit  
       70 天前
    箭头函数没有 this
    zhaomeicheng
        8
    zhaomeicheng  
       70 天前
    1. 箭头函数里的 this 是在箭头函数被定义那一刻决定的,且后续不会再变了。
    2. 箭头函数里的 this 是离它最近的外层普通函数的 this ,如果最外层是全局环境,那么即 window 。

    第一个输出:
    箭头函数定义的那一刻,外层没有普通函数,那么 this 是 window 。
    第二个输出:
    箭头函数定义的那一刻,外层普通函数是 pet 函数,且 pet 函数被调用是通过 new 操作符,所以 pet 函数的 this 是 cat 对象,即箭头函数的 this 是 cat 。
    lisongeee
        9
    lisongeee  
       70 天前
    普通函数的 this 像是一个关键字语法糖,从 ast 的角度看,当这个函数被以 MemberExpression 被调用时,函数内的 this 是 Identifier
    箭头函数的 this 像是一个 const 变量语法糖,当箭头函数被声明时,额外在当前作用域声明了一个 <const>_this ,并将
    这个 _this 永久作为箭头函数内的 this

    ```js
    function Pet(name) {
    this.name = name;
    const _this = this;
    this.getName1 = () => _this .name;
    }
    ```
    QGabriel
        10
    QGabriel  
       70 天前
    1. 箭头函数的 thsi 是上层的 this;
    console.log(pet1.getName1()) 相当于 window.pet1.getName1(); pet1 的 this 是 window

    2. new 方法 会在函数内隐式的声明一个 this 变量 值为空对象; let this = {}
    function pet('Fluffy') {
    this.name ='Fluffy';
    this.getName1 = () => this.name;
    }
    dcsuibian
        11
    dcsuibian  
       70 天前
    一般的函数,都有一个隐藏的 this 参数。例如:
    function add ( a , b ){
    return a+b
    }
    这个函数的完整形式,你可以想象成:
    function add ( this, a , b ){
    return a+b
    }
    我习惯称这种形式为“函数的绝对表示”。

    如果你使用“对象.函数()”的方式调用,那么这个隐藏的 this 参数就会变成那个对象。比如 t.add(1,2),函数中收到的就是 add ( t, 1, 2)。

    但箭头函数,没有这个隐藏的 this 参数,也就是说
    let add=(a,b)=>{
    return a+b
    }
    它的绝对表示也都是这样。
    dcsuibian
        12
    dcsuibian  
       70 天前
    用这种方法理解,那么你的函数:
    function pet(name) {
    this.name = name;
    this.getName1 = () => this.name;
    }
    其实可以看做:
    function pet( this, name) {
    this.name = name;
    this.getName1 = () => {
    return this.name;
    }
    }
    把 this 看成一个普通的参数,那么 this 其实就是使用了闭包机制。
    liuw666
        13
    liuw666  
       70 天前 via iPhone
    写了一年多 react 都是函数组件,好像几乎没用过 this
    Justin13
        14
    Justin13  
       70 天前 via Android
    箭头函数的 this 在声明时确定
    第一个指的是全局作用域,第二个指的是函数作用域
    而通常的 this,指向的是调用者
    karott7
        15
    karott7  
       70 天前
    一楼答案正确且简洁
    xinleibird
        16
    xinleibird  
       70 天前
    箭头函数的执行上下文不持有 ThisBinding ,采用的是 Lexical this (词法指的是执行上下文中的「环境」,理解为以作用域链替换 this 就成了)。其实这样越说越糊涂了……

    ```js
    const obj = {
    detail: "obj",
    getDetail() {
    console.log(this.detail);
    }
    }

    obj.getDetail(); // obj

    const getDetail = obj.getDetail;
    getDetail(); // undefined ,此时上下文是 global ,非严格模式,global 下 this 指向 window ,window 没有 detail
    ```

    ```js
    const obj = {
    detail: "obj",
    getDetail: () => {
    console.log(this.detail);
    },
    };

    obj.getDetail(); // undefined ,「对象字面量」 obj 不产生作用域,这个要注意。this 找上级作用域 window ,window 没有 detail 属性。
    ```
    1. 执行上下文除了 global 其余都是函数执行产生的。
    2. 你在函数中使用的 `this`,也就是执行上下文中的 `ThisBinding`,只与调用该函数的「对象」相关。
    3. 箭头函数是个特殊情况,它采用词法 this ,也就说,`this` 与上下文中「动态的」 ThisBinding ( obj 或 window ,`.`点号之前的……)无关,与「静态的」环境有关,要到环境(作用域链)中找。
    4. 而「对象字面量」`obj` 又不产生作用域(它顶多叫 namespace 名字空间)。由此会再向真正的作用域中找,外层的作用域就是 global ( window )。
    5. **简而言之**:箭头函数的词法 this 产生的效果是:把箭头函数上下文中的 this 绑定到 **『外层作用域』** 中。

    推荐到 https://muyiy.cn/blog/1/1.1.html 看看,博主写的很详细,跟着写写伪代码就清楚了。这样白嘴说其实越说越乱。
    DOLLOR
        17
    DOLLOR  
       70 天前
    上面所有人都忘记提到的一点,非严格模式下,没有经过 let 、const 声明就直接赋值给一个变量名,它就成为全局变量,并且成为 window 下的同名属性。
    比如
    name = "哈哈"
    name 成了全局变量,并且也是 window.name 的值也是"哈哈"。如果在某个函数内 this 误指向了 window ,那么 this.name 的值也是"哈哈"。
    这种特性应该避免误用。
    AyaseEri
        18
    AyaseEri  
       69 天前
    function 才能形成一个作用域吧,单纯字面量的对象并不能形成作用域。

    function Senpai(name) {
    this.name = name;
    return {
    getName1: () => this.name,
    getName2() { return this.name }
    }
    }

    这俩结果也是不一样的
    yaphets666
        19
    yaphets666  
       68 天前
    就一句话,箭头函数的 this 指向和声明位置的 this 指向一致
    huangqihong
        20
    huangqihong  
       68 天前
    看到高手就进来了,看到 this 指向问题就明白了,这无关“高手”的问题,
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   实用小工具   ·   276 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 38ms · UTC 20:19 · PVG 04:19 · LAX 12:19 · JFK 15:19
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.