V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
wjx0912
V2EX  ›  JavaScript

js this 请教

  •  
  •   wjx0912 · 2022-07-26 22:43:01 +08:00 · 2638 次点击
    这是一个创建于 880 天前的主题,其中的信息可能已经有所发展或是发生改变。
    代码:


    为什么输出的是 person2 呢
    18 条回复    2022-07-27 17:33:09 +08:00
    SilentDepth
        1
    SilentDepth  
       2022-07-26 22:52:33 +08:00
    看一下 JS API ,call 方法的第一个参数是啥
    crs0910
        2
    crs0910  
       2022-07-26 22:55:12 +08:00
    The `call()` method calls the function with a given `this` value and `arguments` provided individually.
    DOLLOR
        3
    DOLLOR  
       2022-07-27 00:04:42 +08:00
    调用 person1.foo4.call(person2)时,foo4 里的 this 指向 person2 对象,它返回的箭头函数里的 this 也指向 person2 对象。
    dcsuibian
        4
    dcsuibian  
       2022-07-27 00:20:56 +08:00
    js 方法里其实有个叫 this 的参数,如果你使用
    person1.foo4()这么调用,那么这个 this 会被赋值为 person1 。
    但如果你使用了 call()、apply()、bind()这几个方法,那么你就是在强制指定这个 this 是谁。
    wunonglin
        5
    wunonglin  
       2022-07-27 00:22:34 +08:00
    你 call 了 person2 的 this 进去 person1.foo4 这个方法,那么这个方法的 this 自然就是 person2 咯
    autoxbc
        6
    autoxbc  
       2022-07-27 03:52:11 +08:00
    从 person1 上找到 foo4 ,再把 foo4 上的隐参数 this 绑定为 person2 ,一直到这里,那个箭头函数都还没有生成
    wjx0912
        7
    wjx0912  
    OP
       2022-07-27 08:35:10 +08:00
    感谢各位大佬解答

    @autoxbc 最适合理解的答案,更新大佬半夜回帖
    wjx0912
        8
    wjx0912  
    OP
       2022-07-27 08:46:19 +08:00
    var name = 'window'

    var person1 = {
    name: 'person1',
    foo2: () => console.log(this.name),
    }

    var person2 = { name: 'person2' }


    person1.foo2.call(person2)


    打印结果是‘window’,如果按照上面理解,执行 foo2.call 的时候,箭头函数已经生成了,里面的 this 绑定的是全局 window ,这样对吗?

    也就是说如果返回箭头函数的闭包,直到调用箭头函数的时候 this 才绑定;而赋值箭头函数时,箭头函数的 this 就直接绑定了。这个说法对吗?

    感谢大家
    wjx0912
        10
    wjx0912  
    OP
       2022-07-27 09:02:44 +08:00
    @ymcz852 babel 转之后的确是很清楚了。谢谢
    kevin1
        11
    kevin1  
       2022-07-27 09:18:08 +08:00
    1. 箭头函数不会创建自己的 this ,它只会从自己的作用域链的上一层继承 this 。
    2. 上层 this 被 call 修改成了 person2 。
    wjx0912
        12
    wjx0912  
    OP
       2022-07-27 09:30:59 +08:00


    @kevin1 感谢答复

    按照你说的“上层 this 被 call 修改成了 person2 ”,那这个箭头函数 this 没有被 call 修改成 B 对象。
    是不是第 11 行函数执行后,箭头函数被实例化,在这个时间点绑定 this ?
    johnkiller
        13
    johnkiller  
       2022-07-27 09:40:34 +08:00 via iPhone
    后面的例子,可以参考:函数的作用域是在什么时候确定的
    Curtion
        14
    Curtion  
       2022-07-27 10:19:43 +08:00
    @wjx0912 #12 你在执行第 11 行时就确定了 this 为 A ,而箭头函数 this 无法被修改。 你把第 11 行移动到 B 对象定义之后,然后使用 A.sayHello.call(B),那么后续箭头函数 this 就固定为 B 了。
    wjx0912
        15
    wjx0912  
    OP
       2022-07-27 11:17:57 +08:00
    @johnkiller 谢谢
    @Curtion 谢谢
    kevin1
        16
    kevin1  
       2022-07-27 16:24:25 +08:00
    @wjx0912 12# 你图上左边代码里的箭头函数 s 确实是在第 11 行的时候绑定了。

    箭头函数的 this 是在创建时就已经确定了,不会再改变。
    kevin1
        17
    kevin1  
       2022-07-27 16:38:49 +08:00
    @wjx0912 12# 右边 babel 转码后的代码也能很好的解释这一点。

    左边 11 行代码运行后,实际上用闭包的方式声明了一个局部变量 _this ,这个变量从外部无法改变,所以一旦创建了以后这个值都不会再变了。
    wjx0912
        18
    wjx0912  
    OP
       2022-07-27 17:33:09 +08:00
    @kevin1 是的。基本上理解了。感谢各位
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2650 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 15:23 · PVG 23:23 · LAX 07:23 · JFK 10:23
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.