JavaScript中this的指向问题

前言

        在上一篇文章中,在我们聊的 JavaScript原型对象(prototype)、实例和构造函数(constructor)的关系中,为什么构造函数(constructor) 和类的constructor函数中定义属性需要使用 this?今天我们就来聊一聊 JavaScript 中的this指向问题。

// 构造函数,这里定义使用的this指向哪里?
function MyWorld1(name1, name2, name3) {
    this.name1 = name1
    this.name2 = name2
    this.name3 = name3
}

// 类中constructor函数使用的this又指向哪里?
class Myworld2 {
    constructor(name, grade, figure) {
        this.name = name
        this.grade = grade
        this.figure = figure
    }
    // 实例方法
    InstanceMethod() {
        console.log(`${this.name}触发了实例方法`)
    }
    // 静态方法
    static StaticMethod() {
        console.log(`${this.name}触发了静态方法`)
    }
}

一、this的指向

        在 JavaScript 中,this 的指向是动态绑定的,取决于函数的调用方式,而非定义的位置。

二、核心规则(按优先级排序)

        1、new 绑定

        使用 new 调用构造函数(constructor)时,this 指向新创建的对象:

// 构造函数,这里定义使用的this指向哪里?
function MyWorld1(name1, name2, name3) {
    this.name1 = name1
    this.name2 = name2
    this.name3 = name3
    console.log('MyWorld1的this: ', this)
}

const myworld1 = new MyWorld1('我不叫菜只因', '小美', '王刚')
console.log('myworld1实例: ', myworld1)

        输出结果中明确可以看到:

        1. MyWorld1 构造函数中的 this 在被 new 调用后,就指向了新创建的实例对象 myworld1。

        2、显示绑定

        通过 call()、apply() 或 bind() 强制指定 this

function MyWorld(grade) {
    this.grade = grade
    console.log('MyWorld1函数中的this: ', this)
}

const obj = {
    name1: '我不叫菜只因',
    name2: '小美',
    name3: '王刚',
    id: 'obj'
}

MyWorld.call(obj)
MyWorld.call(obj, '等级0')

        输出结果可以看出 call() 方法的使用,至于 apply() 和 bind() 方法的详细使用,读者可以私下自行查阅,这里不做过多的描述。

        3、隐式绑定

        函数作为对象方法调用时,this 指向调用它的对象:

const MyWorld3 = {
    name: '我不叫菜只因',
    Jump() {
        console.log('MyWorld3.Jump的this指向: ', this, this.name)
    }
}

MyWorld3.Jump()

        输出结果可以看出对象下的函数的this指向是该对象本身

        4、默认绑定

        独立函数调用时,this 指向全局对象(浏览器中为 window,Node.js 中为 global)。严格模式下为 undefined:这边就展示浏览器下的情况

function MyWorld4() {
    console.log('MyWorld4的this指向: ', this)
}
MyWorld4()

        输出结果为浏览器的 window

三、特殊场景

        1、箭头函数

        箭头函数没有自己的 this,继承外层作用域的 this

const Obj = {
    name: 'Obj',
    grade: '等级1',
    id: 111,
    MyWorld6: () => {
        console.log('MyWorld6的this指向: ', this) // 箭头函数的this指向外层的this
    },
    MyWorld7() {
        console.log('MyWorld7的this指向: ', this) // 普通函数的this指向调用它的对象
    },
}
console.log('外层的this指向: ', this)
Obj.MyWorld6()
Obj.MyWorld7()

        输出结果

        2、回调函数

        回调中的 this 由调用方式决定,常见丢失绑定问题:

const user = {
    id: 'user',
    name: '用户',
    Jump() {
        setTimeout(function() {
            console.log('回调函数为普通函数的this指向: ', this) // 默认绑定到 window,丢失user
        }, 100)
    },
    Squat() {
        setTimeout(() => {
            console.log('回调函数为箭头函数的this指向: ', this) // 继承user的this
        }, 100)
    }
}
user.Jump()
user.Squat()

        输出结果

        3、DOM事件处理器

        事件处理函数中的 this 指向触发事件的 DOM 元素:


<!doctype html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
    </head>

    <body>
        <button id="btn">按钮</button>

        <script>
            const btn = document.getElementById('btn')
            btn.addEventListener('click', function() {
                console.log('DOM元素事件处理函数下的this指向: ', this)
            })
            // 不能使用箭头函数,箭头函数会使得 this 指向 window
            btn.addEventListener('click', () => {
                console.log('DOM元素事件处理函数下的this指向: ', this)
            })
        </script>
    </body>
</html>

        输出结果

四、关键注意事项

  • 绑定丢失问题:方法被赋值给变量时可能丢失 this:
const Obj = {
    name: 'Obj',
    grade: '等级1',
    id: 111,
    MyWorld6: () => {
        console.log('MyWorld6的this指向: ', this) // 外层的this是window
    },
    MyWorld7() {
        console.log('MyWorld7的this指向: ', this)
    },
}
const myworld = Obj.MyWorld7
myworld()

        输出结果

  • 严格模式影响:独立调用函数中 this 为 undefined,避免意外修改全局对象。
  • bind的永久性bind() 创建的绑定不可覆盖(优先级最高)。
  • 异步上下文:Promise()、async/await 不影响 this 的规则,仍由调用方式决定。

五、总结表

调用方式this指向示例
new Constructor()新创建的对象new Person()
fn.call(obj)显示指定的对象MyWorld.call(obj, '等级0')
obj.method()调用方法的对象user.Squat()
独立函数调用全局对象/ undefined (严格)MyWorld()
箭头函数外层作用域的 this() => { ... }
DOM事件处理触发事件的DOM元素button.onclick = fn

        理解 this 的关键在于分析函数的调用方式,而非是定义的位置。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值