29前端成长日记 - this

97 阅读3分钟

之前对this的指向感觉是一知半解的,今天做一个总结吧
说到this肯定要提到函数、构造函数和class了

先说函数吧,在普通的函数内this是默认指向window

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

fn() // window

执行fn后可以发现控制台打印出的是window,我们可以在做一个实验

window.a = '我是全局变量a'

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

fn() // 我是全局变量a

这里我先定义了一个全局变量a,然后在函数内打印出this.a可以发现就是刚刚我们为全局变量a赋的值
通过这两个例子就可以确定函数内的this是指向window

我们在看看将函数放在对象中

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

var obj = {
    name: 'ian',
    fn: fn
}

obj.fn() // ian

将函数fn作为对象obj fn 属性的值,然后调用obj.fn()可以发现控制台输出的是ian,所以我们可以理解成谁调用了函数,this就指向谁

function fn(callback){
    callback()
}

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

var obj = {
    name: this,
    fn: fn
}

obj.fn(fn1) // window

声明一个函数fn1将它传入函数fn中执行,obj 在调用 fn 的时候打印出了 window, 记住之前的那句话谁调用了函数,this就指向谁,这里 fn1 只是作为回调函数传到 fn 并没人去调用它
这里有个特例如果使用 es6 的箭头函数结果就不一样了,我们来试试

var fn = ()=>{
    console.log(this)
}

var obj = {
    name: this,
    fn: fn
}

obj.fn() // window

会返现控制台输出的是 window 这是因为箭头函数中没有 this 它的 this 取决于包裹它的普通函数,我们来试试

function fn(){
    return ()=>{
        console.log(this.name)
    }
}

var obj = {
    name: this,
    fn: fn
}

obj.fn()() // ian

下面在来看看构造函数,说到构造函数,那么就要搞清楚在 new 的时候发生了什么

在执行new的时候,会生成一个空对象,并将this指向这个空对象,将构造函数作为空对象的原型

function Fn(){
    this.name = 'ian'
    this.age = 18
}

var fn = new Fn()
// 这里可以翻译成
// var fn
// var obj = {}
// obj.name = 'ian'
// obj.age = 18
// obj.__proto__ = Fn.prototype
// fn = obj
// obj = null

fn.name // 'ian'
fn.age // 18

这里要注意如果构造函数有 return 结果可能又不一样

var obj = {
    name: '小王',
    age: 20
}

function Fn(){
    this.name = 'ian'
    this.age = 18
    return obj
}

var fn = new Fn()

fn.name // 小王
fn.age // 20

如果构造函数 return 了一个对象,那么在 new 的时候 this 是指向这个对象的,那么其他类型呢

function Fn(){
    this.name = 'ian'
    this.age = 18
    return Number(1)
}

function Fn1(){
    this.name = 'ian'
    this.age = 18
    return String('Hello')
}

function Fn2(){
    this.name = 'ian'
    this.age = 18
    return Array('name','age')
}

function Fn3(){
    this.name = 'ian'
    this.age = 18
    return function(){}
}

var fn = new Fn()
var fn1 = new Fn1()
var fn2 = new Fn2()
var fn3 = new Fn3()

fn.name // ian
fn.age // 18
fn1.name // ian
fn1.age // 18
fn2 //['name','age']
fn3 // f(){}

所以只要 return 是一个对象那么 this 就指向这个对象,那如果我return this,或者return的对象中的 this 又指向谁呢?


function fn1(){
    console.log(this.name)
}

function Fn(){
    this.name = 'ian'
    this.age = 18
    return this
}

function Fn1(){
    this.name = 'ian'
    this.age = 18
    return fn1
}

var fn = new Fn()
var fn2 = new Fn1()

fn // {name: "ian", age: 18}
fn1() // ian

可以看出 return 中的this是指向这个构造函数

最后就是classclass 是现有的基于原型的继承的语法糖,它的this是指向实例对象