关于this的调用

一、对象形式

1、引用函数为箭头函数时

    var obj = {
        fn: () => console.log(2, this)
    }
    obj.fn(); // window
    const fn = obj.fn
    fn(); // window

解释

  1. obj.fn();:在这种情况下,fn 是作为 obj 对象的方法被调用的。然而,fn 是一个箭头函数,它会继承外部作用域的 this 值。在全局作用域中,箭头函数的外部作用域是全局作用域,因此 this 指向全局对象(在浏览器中是 window)。所在的作用域其实是最外层的js环境,因为没有其他函数包裹;然后最外层的js环境指向的对象是winodw对象,所以这里的this指向的是window对象。

  2. const fn = obj.fn; fn();:在这种情况下,fn 是将 obj.fn 赋值给一个常量。由于 obj.fn 是一个箭头函数,它会继承外部作用域的 this 值。在这里,箭头函数的外部作用域是全局作用域,因此 this 指向全局对象(在浏览器中是 window)。所以,console.log(2, this) 会打印出 window

总结起来,无论是通过 obj.fn() 还是通过 fn() 调用箭头函数,this 都指向全局对象 window。这是因为箭头函数继承了外部作用域的 this 值,而不是创建自己的 this 值。

疑问:那么如何使this一直指向obj?
    var name = 'window'

    const obj2 = {
        name: '杜甫',
    }
    var obj = {
        name: '李白',
        fn: function () {
            return () => console.log(this.name)
        }
    }
    const fn = obj.fn();
    fn() // 李白
    fn.call(obj2) // 李白
    fn.call()  // 李白

解释:

  1. fn() // 李白:在这种情况下,fn 是作为 obj 对象的方法被调用的。obj.fn() 返回一个箭头函数,并将其赋值给了 fn。由于箭头函数继承了外部作用域的 this 值,所以 this.name 指向 obj 对象的 name 属性,即 '李白'。因此,console.log(this.name) 打印出 '李白'

  2. fn.call(obj2) // 李白:在这种情况下,虽然使用了 call 方法将 fn 的执行上下文更改为 obj2,但是箭头函数仍然继承了外部作用域的 this 值。由于箭头函数的外部作用域是在 fn 被定义时确定的,它是 obj 对象的方法,所以 this.name 仍然指向 obj 对象的 name 属性,即 '李白'。因此,console.log(this.name) 打印出 '李白'

  3. fn.call() // 李白:在这种情况下,call 方法没有传递任何参数,因此 fn 的执行上下文仍然是全局对象(在浏览器中是 window)。由于箭头函数继承了外部作用域的 this 值,所以 this.name 指向全局对象的 name 属性,即 'window'。然而,在全局作用域中并没有定义名为 name 的变量,所以 this.name 的值是 undefined。因此,console.log(this.name) 打印出 undefined

总结起来,无论如何改变箭头函数的执行上下文,它仍然会继承外部作用域的 this 值。在这段代码中,箭头函数继承了 obj 对象的方法的 this 值,因此无论如何调用箭头函数,this.name 都指向 obj 对象的 name 属性,即 '李白'

2、引用函数为普通函数时

    var obj = {
        fn: function () {
            console.log(this);
        }
    }
    obj.fn(); // obj
    const fn = obj.fn
    fn(); // window

解释:

this 的值取决于函数如何被调用。这就是所谓的函数调用的上下文(context)。以下是对这段代码的分析:

  1. obj.fn();:在这种情况下,fn 是作为 obj 对象的方法被调用的。因此,this 在 fn 函数内部指向 obj。这就是为什么 console.log(this); 会打印出 obj 对象。

  2. const fn = obj.fn; fn();:在这种情况下,fn 是作为一个独立的函数被调用的,而不是作为 obj 的方法。在非严格模式下,当一个函数独立调用(即它不是作为对象的方法调用)时,this 通常会指向全局对象(在浏览器中是 window)。因此,console.log(this); 会打印出 window。如果你在严格模式下运行这段代码(即在代码的顶部添加 "use strict";),this 会是 undefined,因为严格模式下,独立函数调用不会默认 this 到全局对象。

这就是为什么在这段代码中,this 在两种情况下有不同的值。

疑问:对象嵌套的情况呢?

    var name = 'window'

    var obj = {
        name: '李白',
        age: {
            name: 'age',
            fn: function () { console.log(this.name) }
        }

    };
    obj.age.fn()  //age
同上述一样,箭头函数指向window,解构出来也是window,如果是普通函数就是所在对象本身

三、进阶

    var name = 'window'

    var obj = {
        name: '李白',
        fn: () => console.log(this.name),
        fn2: function () { console.log(this.name) }

    };
    (obj.fn = obj.fn)();  //window
    (obj.fn2 = obj.fn2)()  //window
  1. (obj.fn = obj.fn)(); // window:在这种情况下,obj.fn 是一个箭头函数,并将其赋值给了 obj.fn。然后,(obj.fn = obj.fn) 表达式将箭头函数赋值给了 obj.fn,但是由于箭头函数继承了外部作用域的 this 值,所以 this.name 指向全局对象(在浏览器中是 window)。因此,console.log(this.name) 打印出 'window'

  2. (obj.fn2 = obj.fn2)(); // window:在这种情况下,obj.fn2 是一个普通函数,并将其赋值给了 obj.fn2。然后,(obj.fn2 = obj.fn2) 表达式将普通函数赋值给了 obj.fn2。普通函数的 this 值是在执行时确定的,而不是在定义时确定的。因此,当 (obj.fn2 = obj.fn2)() 被调用时,this 指向全局对象(在浏览器中是 window)。因此,console.log(this.name) 打印出 'window'

无论是箭头函数还是普通函数,当它们作为对象的方法被调用时,它们的 this 值都指向全局对象 window。这是因为在这段代码中,对象的方法被直接调用,而不是通过对象的引用进行调用。因此,函数的执行上下文是全局对象。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值