ES5函数中的this和ES6箭头函数中的this

我们都知道,js中的变量是遵循词法作用域(也叫静态作用域)的,如:

let a = 'global'
function foo1() {
    let a = 'local'
    console.log(a)
    function foo2() {
        console.log(a)
    }
    foo2()
}
foo1()

上面函数打印出的结果为2个‘local’,因为foo2函数中没有定义变量a,因此在函数会沿着作用域向上找,直到找到foo1中的a。

我们把这里的变量a想象成this:

function foo1() {
    console.log(this)
    function foo2() {
        console.log(this)
    }
    foo2()
}
foo1.call({name: 'zhangsan'})

上面函数打印出来的是{name: ‘zhangsan’}对象和window对象,因此这里的this是不遵循词法作用域的,如果没有给foo2传this,它这里不会沿着函数往上找的,而是直接就定义为window对象,所以以前如果要用foo1中的this,就必须把它传给foo2,常见的写法有三种:
法一:

function foo1() {
    console.log(this)
    let _this = this
    function foo2() {
        console.log(_this)
    }
    foo2()
}
foo1.call({name: 'zhangsan'})

这种写法是将this转化成一个普通变量, 这样就遵循词法作用域了, 于是两次打印的结果一样,均打印出{name:’zhangsan’},foo2中的_this就是foo1中的_this,也就是foo1中的this。
法二:

function foo1() {
    console.log(this)
    function foo2() {
        console.log(this)
    }
    foo2.call(this)
}
foo1.call({name: 'zhangsan'})

这种写法是将foo1中的this通过call函数传递给foo2,这样两处的this就是一样的了,同样打印出的结果为2个{name: ‘zhangsan’}
法三:

function foo1() {
    console.log(this)
    function foo2() {
        console.log(this)
    }
    foo2.bind(this).call()
}
foo1.bind({name: 'zhangsan'}).call()

上述方法和第二种其实是一样的,只是先将实参通过bind函数进行传递,然后再调用函数,输出的结果同样是2个{name: ‘zhangsan’}

以上这些都是为了让this能像具有词法作用域的普通变量一样使用,终于,ES6迎来了箭头函数,让我们不用做如此多的挣扎,便可以像使用普通变量一样使用this

function foo1() {
    console.log(this)
    let foo2 = () => {
        console.log(this)
    }
    foo2.call()
}
foo1.call({name: 'zhangsan'})

这里将foo2声明为箭头函数,得到的结果就是2个{name: ‘zhangsan’}啦,很神奇有木有?

当然,箭头函数中的this也有一些奇葩的地方,如:
···
let foo3 = () => {
console.log(this)
}
foo3.call({name: ‘zhangsan’})
···
这里输出的结果是window,也就是说箭头函数中的this已经彻底颠覆了我们以前对this的看法:call函数的第一个参数,也就是在箭头函数中this已经不是call函数的第一个参数了,它已经彻彻底底沦为一个和遵循词法作用域的普通变量啦!

猜你喜欢

转载自blog.csdn.net/m0_38102188/article/details/81502946