this/apply/call/bind

155 阅读1分钟

测试代码

var name = "windowsname"
        var a = {
            age: 10,
            f1() {
                console.log(this.name, this.age)
            },
            f2: () => {
                console.log('===箭头函数f2===')
                console.log(this.name, this.age)
            },
            f3() {
                setTimeout(() => {
                    console.log('===箭头函数f3===')
                    this.f1()
                }, 0);
            },
            f4() {
                window.setTimeout(function () {
                    this.f1()
                }, 0);
            },
            f5() {
                window.setTimeout(function () {
                    console.log('===apply===')
                    this.f1()
                }.apply(a), 0);
                setTimeout(function () {
                    console.log('===call===')
                    this.f1()
                }.call(a), 0);
                setTimeout(function () {
                    console.log('===bind===')
                    this.f1()
                }.bind(a)(), 0);
                const _this = this;
                setTimeout(function () {
                    console.log('===_this===', this, _this)
                    _this.f1()
                }, 0);
            },
            f6: function() {
                const _this = this
                const test = () => {
                    console.log('箭头函数f6')
                    this.f1()
                }
                test()
            }
        }
        a.f1()
        a.f2()
        a.f3()
        // a.f4()
        a.f5()
        a.f6()
        var f = a.f1;
        console.log('===f===')
        f()

测试结果

undefined 10
===箭头函数f2===
windowsname undefined
===apply===
undefined 10
===call===
undefined 10
===bind===
undefined 10
箭头函数f6
undefined 10
===f===
windowsname undefined
===箭头函数f3===
undefined 10
===_this=== Window {window: Window, self: Window, document: document, name: 'windowsname', location: Location, …} {age: 10, f1: ƒ, f2: ƒ, f3: ƒ, f4: ƒ, …}
undefined 10

总结

this 指向

es5 中,永远是 this 永远指向最后调用它的那个对象。(一定注意是最后调用的对象。)

这个也就是为什么如果把 var f = a.f1f() 之后调用的结果和直接 a.f1() 不一样的原因了。

如何改变 this 的指向?

  • es6 的箭头函数
  • _this = this
  • applycallbind
  • new 实例化一个对象

箭头函数的 this 指向

始终指向函数定义时的 this,而不是执行时的。

箭头函数中没有 this 绑定,必须通过查找作用域链来决定其值,如果箭头函数被非箭头函数包含,则 this 绑定的是最近一层非箭头函数的 this

什么时候该用/不该用箭头函数

不该用

  • 定义对象的方法(包括字面量方法及原型方法)
  • 定义事件回调函数
  • 定义构造函数

其他都可以使用,尤其是回调中需要固定 this 指向的时候

引用

什么时候你不能使用箭头函数?