JS的this指向

this的概念

  • this是一个指针型变量,动态指向当前函数的运行环境。
  • this永远指向函数的真实调用者,也就是离被调用的函数最近的那个对象(箭头函数除外),如果没有调用者,就指向window对象,例如全局函数,其实window对象就是调用者,只是省略不写。
  • 箭头函数没有自己的this,会捕获外层函数作用下的this,如果遇到箭头函数,继续往上找,直到找到普通函数作用域,如果最后没有找到,那就指向window对象。另外箭头函数的this在定义时就会被固定。箭头函数使用call,apply,bind也无法改变this指向。
  • 构造函数的this指向实例
  • 可以使用call,apply,bind改变this指向,注意箭头函数this指向无法改变。

看几个例子

var obj2 = {
    name: 'obj2',
    say: function () {
        return function() {
            console.log(this);
        }
    }
}
obj2.say()() // window,因为obj2.say()返回的是一个函数,然后这个函数被调用了,调用者是window

var obj2 = {
    name: 'obj2',
    say: function () {
        return () => {
            console.log(this);
        }
    }
}
// 箭头函数在定义时this已经固定了,
// 箭头函数本身没有this对象,会一直往上找作用域的this对象,也就是say函数作用域下的this对象,而say函数由obj2调用,所以this指向obj2
obj2.say()() // obj2

var obj2 = {
    name: 'obj2',
    say: function () {
        this.a = 'a' // this指向obj2
        return function() {
            return function() {
                console.log(this);
            }
        }
    }
}
obj2.say()()() // window,因为obj2.say()()返回一个函数,调用者是window

var obj2 = {
    name: 'obj2',
    say: function () {
        this.a = 'a'
        return () => {
            return () => {
                console.log(this);
            }
        }
    }
}
obj2.say()()() // obj2,箭头函数会往上找外层函数作用域下的this对象,直到找到可用的this对象

var obj2 = {
    name: 'obj2',
    say: function () {
        this.a = 'a'
        return () => {
            return function() {
                console.log(this);
            }
        }
    }
}
obj2.say()()() // window,obj2.say()()是函数,调用者是window

var obj2 = {
    name: 'obj2',
    say: function () {
        this.a = 'a'
        return function foo() {
            return () => {
                console.log(this);
            }
        }
    }
}
obj2.say()()() // window,这里比较复杂
// obj2.say()() == foo,foo的调用者其实就是window,所以foo的this指向是window
// 然后obj2.say()()()执行的箭头函数,箭头函数在定义的时候this已经固定,就是往上找到的foo作用域的this对象,也就是window

var obj2 = {
    name: 'obj2',
    say: function () {
        this.a = 'a'
        return obj = {
            name: 'foo',
            fn() {
                console.log(this);
            }
        }
    }
}
obj2.say().fn() // obj,因为obj2.say()返回obj对象,obj是fn的调用者

严格模式下的this

严格模式下,我们对代码的调用必需写上调用者,不得省略

function fn() {
    'use strict'
    console.log(this);
}
fn() // undefined
window.fn() // window

箭头函数的this

  • 箭头函数没有自己的this,会捕获外层函数作用下的this,如果遇到箭头函数,继续往上找,直到找到普通函数作用域,如果最后没有找到,那就指向window对象。另外箭头函数的this在定义时就会被固定。
  • 箭头函数使用call,apply,bind也无法改变this指向
  • 箭头函数没有arguments对象
var obj = {
    fn:()=>{
        console.log(this);
    }
}
obj.fn() // window,往上找没有找到函数作用域,所以是window

var obj2 = {
    name: 'obj2',
    say: () => {
        return {
            name: 'foo',
            fn: () => {
                console.log(this);
            }
        }
    }
}
obj2.say().fn() // window,往上找先找到say函数作用域,但是say是箭头函数,继续往上找,没找到函数作用域,所以最后是window

var obj2 = {
    name: 'obj2',
    say() {
        return {
            name: 'foo',
            fn: () => {
                console.log(this);
            }
        }
    }
}
obj2.say().fn() // obj2,往上找找到say函数作用域,并且say是普通函数,因为obj2.say()下say的调用者是obj2,所以say作用域的this指向obj2

构造函数的this

构造函数的this指向实例

改变this指向的方法

callapplybind