如何确定this的值?

63 阅读2分钟

引言

在面试过程中,你可能遇到过这样子的题目:

var length = 4

function callback() {
    console.log(this.length)
}
var obj = {
    length: 5,
    methods(callback) {
        callback()
    }
}

obj.methods(callback,1,2)

打印出来的值是什么?

确定this的值

想要确定this的值,先要熟悉一下函数调用常见的三种方式

1. func(param1,params2)
2. obj.func(param1,params2)
3. func.call(context,param1,params2)

前两种方式是我们最常使用的方式,但其实第三种调用方式才是正常的方式,而且前两种方式其实是第三种方式的语法糖。前两种方式,都可以转换第三种方式:

1. func(param1,params2) => func.call(undefined,param1,param2) // 这里的this为undefined
2. obj.func(param1,params2) => obj.func.call(obj.func,param1,param2) // 这里的this为obj.func

了解了调用方式,就可以确定this了:this就是call()的第一个参数。有人会提出疑问,那第一种方式种的this就是undefined了,this怎么会是undefined呢?其实浏览器里有一条规则:

如果你传的 context 是 null 或 undefined,那么 window 对象就是默认的 context(严格模式下默认 context 是 undefined)

因此第一种方式的打印结果是 window。

让我们来看一段代码:

function fn() {
    console.log(this)
}
fn()

上面的代码可以转换为:

function fn() {
    console.log(this)
}
fn.calll(undefined)

由于浏览器会将null转换undefined转换为window,所以这边的this是window。

再来练练手:

var obj = {
    methods:function() {
        callback()
    }
}
obj.methods()

上面的代码可以转换为:

var obj = {
    methods:function() {
        callback()
    }
}
obj.methods.call(obj)

所以这边的this是obj。

[]语法

function fn(){
    console.log(this)
}
var arr = [fn,1,2,3]
arr[0]()

这里的this是什么呢?我们可以转换一下代码:

上面的arr0 相当于: arr.0() 相当于 arr.0.call(arr)

所以可以确定this为arr

箭头函数

箭头函数的并没有this,如果在箭头函数中用到this,其实这个this就是箭头函数外面的this.

那么,引言中的this是什么呢?你学废了吗?